当前位置: 首页 > news >正文

网站管理建设的需求分析个人网页设计作品论文

网站管理建设的需求分析,个人网页设计作品论文,移动网站模板,公司简介怎样写目录 认识Java对象头 sychronized锁原理 基本概念 工作原理 1.作用在方法上 2.作用在代码块上 工作机制 JVM优化锁 Monitor锁 wait/notify park/unpark 线程状态转换案例 死锁 概念 死锁发生的必要条件 哲学家问题 活锁 饥饿 概念 饥饿的原因 Reentrant…目录 认识Java对象头 sychronized锁原理 基本概念 工作原理  1.作用在方法上 2.作用在代码块上 工作机制 JVM优化锁 Monitor锁 wait/notify park/unpark 线程状态转换案例  死锁 概念 死锁发生的必要条件 哲学家问题 活锁 饥饿  概念 饥饿的原因 ReentrantLock  基本锁操作 查看锁状态的方法 条件变量相关的方法 可重入锁 可打断(lockInterruptibly) 不可打断  锁超时(tryLock) 立刻返回 ​编辑 超时释放  公平锁/非公平锁  非公平锁 公平锁 ​编辑 await/Condition 等待条件await方法系列 通知条件signal方法系列 认识Java对象头 32位虚拟机对象头 64位虚拟机对象头  1.Mark Word标记字: Mark Word是对象头的一部分用于存储对象自身的哈希码、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID或偏向时间戳、偏向模式以及锁的状态等信息。标记字的大小和具体内容可能因JVM实现的不同而有所变化。例如在64位JVM上默认情况下Mark Word占用64位8字节而在32位JVM上则是32位4字节。 2.Class Pointer类指针: 这是指向该对象对应类Class的指针通过这个指针可以访问到对象所属类的元数据如方法表、字段描述等。类指针的大小依赖于JVM的具体实现及其是否开启了压缩指针Compressed Oop选项。在某些情况下比如当使用了-XX:UseCompressedClassPointers选项时类指针会被压缩以节省内存。 3.Array Length数组长度仅适用于数组对象: 如果对象是一个数组则对象头还需要额外的空间来存储数组的长度。这是因为非数组对象不需要知道其“长度”但数组需要这个信息以便进行边界检查等操作。 sychronized锁原理 基本概念 对象头Object Header每个Java对象都有一个对象头其中包含了一些元数据信息。对于普通对象来说这部分包括Mark Word和Class Pointer。Mark Word存储了对象的哈希码、GC分代年龄、锁状态标志等信息。Monitor监视器/管程这是JVM内部的一种同步机制。每个对象都关联有一个监视器锁。当一个线程获取到这个锁时它可以进入临界区其他试图进入同一临界区的线程必须等待直到第一个线程释放锁。 工作原理  1.作用在方法上 使用synchronized修饰一个实例方法时该方法被调用时会自动获取当前实例即this的monitor锁。如果是静态方法则锁定的是该类的Class对象。 2.作用在代码块上 使用synchronized代码块可以更灵活地指定要锁定的对象获取的是括号中的对象。 工作机制 字节码层面使用synchronized关键字时编译器会将同步块或方法转换为特定的字节码指令。对于同步方法编译器会在方法信息中设置一个标志位ACC_SYNCHRONIZED。对于同步代码块则会生成monitorenter和monitorexit指令。 monitorenter 和 monitorexit 指令 monitorenter每个对象都有一个与之关联的monitor监视器锁。当线程执行到monitorenter指令时它尝试获取该对象的monitor。如果monitor未被其他线程持有则当前线程成功获取monitor并继续执行否则线程将被阻塞直到获得monitor。monitorexit当线程执行完同步代码块后会执行monitorexit指令以释放monitor允许其他等待获取该monitor的线程继续执行。 public class Test2 {static final Object lock new Object();static int cnt 0;public static void main(String[] args) {synchronized (lock) {cnt ;}} } 上段代码main方法生成的字节码指令如下 public static void main(java.lang.String[]);Code:0: getstatic #2 // Field lock:Ljava/lang/Object;3: dup4: astore_15: monitorenter // 获取锁6: getstatic #3 // Field cnt:I9: iconst_110: iadd11: putstatic #3 // Field cnt:I14: aload_115: monitorexit // 释放锁16: goto 2419: astore_220: aload_121: monitorexit // 确保在异常情况下也释放锁22: aload_223: athrow24: returnException table:from to target type6 16 19 any19 22 19 any JVM优化锁 1.无锁状态 这是对象的初始状态没有任何线程持有该对象的Monitor锁。 2.偏向锁Biased Locking 偏向锁是针对单线程访问场景的一种优化。它假设如果一个线程获得了某个对象的锁那么接下来很可能还是这个线程继续访问该对象。当一个线程第一次进入同步块时会尝试获取偏向锁并将线程ID记录在对象头中。如果之后还是同一个线程进入同步块则不需要再次获取锁减少了锁获取的开销。如果有其他线程试图获取偏向锁则需要撤销偏向锁并升级为轻量级锁。 3.轻量级锁Lightweight Locking 当存在少量锁竞争时使用轻量级锁来代替重量级锁以提高性能。轻量级锁通过CASCompare And Swap操作尝试原子性地获得锁。如果成功则线程可以进入临界区如果失败表示存在锁竞争锁可能会升级为重量级锁。 4.重量级锁Heavyweight Locking 当锁竞争加剧时JVM会将锁升级为重量级锁。重量级锁涉及到操作系统层面的线程挂起和恢复操作因此开销较大。在这种状态下所有竞争锁的线程都会被阻塞直到当前持有锁的线程释放锁为止。 5.自旋锁Spin Lock 自旋锁不是一种独立的锁类型而是一种策略。当一个线程尝试获取锁时它可以选择“自旋”一段时间而不是立即进入阻塞状态。这样可以在等待锁释放的过程中减少上下文切换的开销。Java中的自旋锁通常与轻量级锁结合使用在某些情况下可以作为一种优化手段。 6.可重入锁Reentrant Lock synchronized机制本身就是可重入的这意味着如果一个线程已经持有了某个对象的锁它可以再次获取相同的锁而不会导致死锁。每次重新获取锁时计数器会增加每次释放锁时计数器会减少直到计数器归零才真正释放锁。 在Java中默认第一次给对象加锁就是偏向锁默认延迟加载假如t1线程已经给obj加上锁偏向锁了当有另外一个线程t2也试图获取同一把锁时偏向锁升级为轻量级锁。 轻量级锁通过使用CAS操作尝试将对象头中的Mark Word更新为指向当前线程的Lock Record的指针。如果成功则线程获得了轻量级锁并继续执行如果失败意味着存在锁竞争则会尝试进行锁膨胀轻量级锁尝试升级为重量级锁。 重量级锁的核心是Monitor监视器锁如果Monitor已被其他线程持有则试图获取锁的线程将被放入Entry Set中等待。此时线程会进入阻塞状态即线程会被挂起不会占用CPU资源直到Monitor锁被释放并且该线程有机会重新尝试获取锁这允许Entry Set中的一个或多个线程重新竞争Monitor锁。如果有线程处于Wait Set中那么根据调用的是notify()还是notifyAll()方法相应的线程会被移动到Entry Set中重新参与Monitor锁的竞争。 Monitor锁 Owner所有者指向当前持有Monitor的线程。Entry Set入口集等待获取Monitor锁的线程队列。如果一个线程尝试进入一个已经被其他线程持有的同步块或方法则该线程会被放入这个队列中直到Monitor被释放并且该线程有机会重新尝试获取锁。Wait Set等待集调用了wait()方法并正在等待某个条件满足的线程集合。这些线程暂时释放了Monitor并且不会参与锁的竞争直到另一个线程调用notify()或notifyAll()方法通知它们可以继续执行。 wait/notify wait()使当前线程等待直到另一个线程调用同一个对象上的notify()或notifyAll()方法。调用wait()时当前线程会释放它持有的对象锁并进入该对象的“等待集”。只有当其他线程调用了相应的通知方法并且当前线程被选中对于notify()或所有等待的线程都被唤醒对于notifyAll()当前线程才能重新获取锁并继续执行。notify()随机唤醒一个正在等待该对象监视器的单个线程。如果多个线程都在等待则选择其中一个线程进行唤醒。被唤醒的线程并不能立即执行而是要等到当前线程退出同步代码块并释放锁之后。notifyAll()唤醒所有正在等待该对象监视器的线程。尽管所有线程都会被唤醒但只有一个线程能够成功获得锁并继续执行其余线程将再次进入等待状态或者竞争锁。 final static Object lock new Object();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(()-{synchronized (lock) {log.debug(running {}, System.currentTimeMillis());try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}log.debug(end... {}, System.currentTimeMillis());}},t1);Thread t2 new Thread(()-{synchronized (lock) {log.debug(running {}, System.currentTimeMillis());try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}log.debug(end... {}, System.currentTimeMillis());}}, t2);t1.start();t2.start();Thread.sleep(2000);synchronized (lock) {log.debug(唤醒线程);// lock.notify(); // 唤醒一个线程lock.notifyAll(); // 唤醒所有线程}} 调用wait就是当前线程得到了对象锁了但是我不往下执行了我把锁释放给其他线程先去执行我自己到Wait Set等待集中去有人线程叫我notify我再去排队进入Entry Set入口集每有人叫我我就继续等着。感觉很像坐高铁我虽然进了高铁站但是车次没有轮到我那么我就继续等着如果叫到我了我就去排队等待坐车 park/unpark 它们是 LockSupport 类中的方法 // 暂停当前线程 LockSupport.park(); // 恢复某个线程的运行 LockSupport.unpark(暂停线程对象) Slf4j(topic c.thread) public class Test4 {public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {log.debug(t1 running {}, System.currentTimeMillis());LockSupport.park();log.debug(t1 end {}, System.currentTimeMillis());}, t1);t1.start();sleep(1000);LockSupport.unpark(t1);} }执行结果 16:10:58 [t1] c.thread - t1 running 1742631058230 16:10:59 [t1] c.thread - t1 end 1742631059240 线程状态转换案例  Slf4j(topic c.thread) public class Test5 {private static final Object obj new Object();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {synchronized (obj) {log.debug(running t1);try {sleep(1000);obj.notify();} catch (InterruptedException e) {e.printStackTrace();}}});Thread t2 new Thread(() - {synchronized (obj) {log.debug(running t2);try {obj.wait();} catch (InterruptedException e) {e.printStackTrace();}}}, t2);Thread t3 new Thread(() - {synchronized (obj) {log.debug(running t3);try {obj.wait();} catch (InterruptedException e) {e.printStackTrace();}}}, t2);t1.start();t2.start();t3.start();log.debug(t1 {} t2 {} t3 {}, t1.getState(), t2.getState(), t3.getState());sleep(100);log.debug(t1 {} t2 {} t3 {}, t1.getState(), t2.getState(), t3.getState());sleep(2000);log.debug(t1 {} t2 {} t3 {}, t1.getState(), t2.getState(), t3.getState());} } 运行结果 21:08:27 [main] c.thread - t1 RUNNABLE t2 RUNNABLE t3 RUNNABLE 21:08:27 [t2] c.thread - running t2 21:08:27 [t2] c.thread - running t3 21:08:27 [Thread-0] c.thread - running t1 21:08:27 [main] c.thread - t1 TIMED_WAITING t2 WAITING t3 WAITING 21:08:29 [main] c.thread - t1 TERMINATED t2 TERMINATED t3 WAITING  第一次打印分析三个线程都启动了 第二次打印分析此时t1在sleept2和t3都在wait 第三次打印分析t1sleep完了然后随机唤醒一个waiting的线程所以t1和t2都执行完了t3没有人唤醒它 死锁 概念 死锁Deadlock是指两个或更多线程在执行过程中由于争夺资源而造成的一种互相等待的状态。在这种状态下没有任何线程能够继续前进整个系统或部分系统因此陷入停滞。死锁是并发编程中常见的问题之一尤其是在多线程环境下对共享资源进行访问时。 死锁发生的必要条件 互斥条件至少有一个资源必须处于非共享模式即只能被一个线程占用。例如文件写入权限通常就是互斥的。占有并等待条件一个线程已经占有了至少一个资源并且正在等待其他线程占有的资源。也就是说该线程不会释放自己已获得的资源直到它获得了所有需要的资源。不可剥夺条件资源不能被强制从某个线程中抢走只能由拥有它的线程主动释放。这意味着一旦一个线程获得了某个资源它可以在不自愿的情况下保持对该资源的控制权直到它完成任务并释放资源。循环等待条件存在一组等待资源的线程链其中每个线程都在等待下一个线程当前占有的资源。例如线程A等待线程B持有的资源而线程B又在等待线程C持有的资源以此类推直到某一线程又在等待线程A持有的资源形成一个闭环。  一个线程同时获取多把锁就容易导致死锁 Slf4j(topic c.Test6) public class Test6 {static Object lockA new Object();static Object lockB new Object();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {synchronized (lockA) {log.debug(lockA {}, Thread.currentThread().getName());synchronized (lockB) {log.debug(lockB {}, Thread.currentThread().getName());try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}, t1);Thread t2 new Thread(() - {synchronized (lockB) {log.debug(lockB {}, Thread.currentThread().getName());synchronized (lockA) {log.debug(lockA {}, Thread.currentThread().getName());try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}, t2);t1.start();t2.start();log.debug(t1 {} t2 {}, t1.getState(), t2.getState());sleep(100);log.debug(t1 {} t2 {}, t1.getState(), t2.getState());sleep(2000);log.debug(t1 {} t2 {}, t1.getState(), t2.getState());}} 分析 t1获得lockA的锁t2获得lockB的锁t1、t2都上锁成功然后t1想要获得lockB但是lockB被t2占有t2只有等到全部执行完才能释放锁但是t2中又要获得lockA的锁但是lockA的锁被t1占有又回到t1t1也只能是执行完才能释放锁然后t1和t2就互相等待对方放锁造成死锁。  ---- 定位死锁的工具jconsole 哲学家问题 有五位哲学家围坐在圆桌旁。 他们只做两件事思考和吃饭思考一会吃口饭吃完饭后接着思考。 吃饭时要用两根筷子吃桌上共有 5 根筷子每位哲学家左右手边各有一根筷子。 如果筷子被身边的人拿着自己就得等待 package cn.itcast.sychronized;import lombok.extern.slf4j.Slf4j;Slf4j(topic c.Test7) public class Test7 {public static void main(String[] args) {ChopSticks c1 new ChopSticks(1);ChopSticks c2 new ChopSticks(2);ChopSticks c3 new ChopSticks(3);ChopSticks c4 new ChopSticks(4);ChopSticks c5 new ChopSticks(5);Philosopher p1 new Philosopher(p1, c1, c2);Philosopher p2 new Philosopher(p2, c2, c3);Philosopher p3 new Philosopher(p3, c3, c4);Philosopher p4 new Philosopher(p4, c4, c5);Philosopher p5 new Philosopher(p5, c5, c1);p1.start();p2.start();p3.start();p4.start();p5.start();} } class ChopSticks {String name;public ChopSticks(String name) {this.name name;}Overridepublic String toString() {return 筷子 { name };} } Slf4j(topic c.Philosopher) class Philosopher extends Thread{final ChopSticks left;final ChopSticks right;public Philosopher(String name, ChopSticks left, ChopSticks right) {super(name); // 线程名字this.left left;this.right right;}public void eat() {log.debug({} eat, Thread.currentThread().getName());}Overridepublic void run() {while (true) {synchronized (left) {synchronized (right) {eat();}}}} } 活锁 活锁Livelock是并发编程中的一种问题类似于死锁但它涉及的是线程虽然没有被阻塞但却无法继续向前推进的情况。在活锁的情况下线程不断地尝试执行某项操作但总是失败并且不断地重复相同的操作导致它们实际上没有取得任何进展。这种现象通常发生在试图避免死锁的过程中特别是当多个线程相互改变状态以试图解决另一个线程的问题时。 活锁出现在两个线程互相改变对方的结束条件最后谁也无法结束。 Slf4j(topic c.Test8) public class Test8 {static volatile int cnt 0;public static void main(String[] args) {new Thread(() - {while (cnt 0) {cnt --;try {sleep(100);} catch (InterruptedException e) {e.printStackTrace();}log.debug(t1 : {}, cnt);}}, t1).start();new Thread(() - {while (cnt 100) {cnt ;try {sleep(100);} catch (InterruptedException e) {e.printStackTrace();}log.debug(t2 : {}, cnt);}}, t2).start();} }饥饿  概念 “饥饿”Starvation是指一个线程由于无法获得所需的资源而无法继续执行的情况。尽管该线程没有被阻塞但由于其他线程频繁地抢占资源导致这个线程得不到足够的CPU时间或其他必要的资源来推进其任务 饥饿的原因 资源竞争当多个线程竞争有限的资源时如果没有公平的调度机制某些线程可能会始终得不到资源从而导致饥饿。例如如果系统总是优先处理高优先级的任务那么低优先级的任务可能永远得不到执行的机会。不恰当的锁机制在使用锁进行同步控制时如果某个线程长时间持有锁而不释放其他等待该锁的线程就会被阻塞可能导致这些线程出现饥饿现象。忙等待Busy-waiting如果一个线程通过忙等待的方式来等待某个条件成立而这个条件很少或几乎不会成立那么这个线程就会一直消耗CPU资源同时无法完成实际的工作。不公平的调度器操作系统或运行时环境中的线程调度器如果没有实现公平调度算法也可能导致某些线程长期得不到执行机会。  ReentrantLock  ReentrantLock reentrantLock new ReentrantLock(true); reentrantLock.lock(); try {     // 临界区代码 } finally {     reentrantLock.unlock() } ReentrantLock(false) : 非公平锁 ReentrantLock(true) : 公平锁 Slf4j(topic c.Test) public class Test {private static final ReentrantLock reentrantLock new ReentrantLock(true);static int cnt 0;public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {reentrantLock.lock();try {for (int i 0; i 10000; i) {cnt;}} finally {reentrantLock.unlock();}}, t1);Thread t2 new Thread(() - {reentrantLock.lock();try {for (int i 0; i 10000; i) {cnt--;}} finally {reentrantLock.unlock();}}, t2);t1.start();t2.start();t1.join();t2.join();log.debug({},cnt);} } 基本锁操作 lock() 获取锁。如果锁已经被其他线程持有则当前线程将被阻塞直到获取到锁为止。 lockInterruptibly() throws InterruptedException 获取锁但可以响应中断。如果当前线程在等待获取锁的过程中被中断则抛出 InterruptedException 异常并退出等待状态。 tryLock() 尝试获取锁如果锁未被其他线程持有则立即返回 true否则立即返回 false不会阻塞当前线程。 tryLock(long timeout, TimeUnit unit) throws InterruptedException 在给定的时间内尝试获取锁。如果在指定时间内成功获取锁则返回 true如果超时或者当前线程被中断则返回 false 或抛出 InterruptedException。 unlock() 释放锁。每次调用 lock() 方法获得一次锁后必须对应地调用一次 unlock() 来释放锁。通常在 finally 块中调用以确保即使发生异常也能正确释放锁。 查看锁状态的方法 isHeldByCurrentThread()判断当前线程是否持有该锁。getHoldCount()返回当前线程获取这个锁的次数重入计数。每次调用 lock() 方法都会增加计数每次调用 unlock() 方法都会减少计数。isLocked()判断锁是否被任意一个线程持有。hasQueuedThreads()查询是否有线程正在等待获取此锁。 条件变量相关的方法 newCondition() 创建一个新的 Condition 实例与当前锁关联。可以使用条件变量来实现类似于 Object.wait() 和 Object.notify() 的功能但更加灵活和强大。 可重入锁 这是指一个线程可以尝试多次获取同一个锁并且不会发生死锁的情况。每次获取锁调用lock()方法都需要相应的释放锁调用unlock()方法。锁获取次数与锁释放次数需要匹配。 // ReentrantLock 可重入锁 Slf4j(topic c.Test2) public class Test2 {final static ReentrantLock reentrantLock new ReentrantLock();public static void method1() {reentrantLock.lock();try {log.debug(method1 running);method2();} finally {reentrantLock.unlock();}}public static void method2() {reentrantLock.lock();try {log.debug(method2 running);method3();} finally {reentrantLock.unlock();}}public static void method3() {reentrantLock.lock();try {log.debug(method3 running);} finally {reentrantLock.unlock();}}public static void main(String[] args) {method1();} }执行结果 10:17:12 [main] c.Test2 - method1 running 10:17:12 [main] c.Test2 - method2 running 10:17:12 [main] c.Test2 - method3 running  可打断(lockInterruptibly) 这个方法允许你以一种可以响应中断的方式获取锁。如果当前线程在调用lockInterruptibly()方法时没有被打断并且能够获取到锁则它将继续执行但如果此时有另一个线程已经持有了这个锁那么当前线程将被阻塞直到锁可用或当前线程被中断。 如果在等待获取锁的过程中收到了中断请求即另一个线程调用了当前线程的interrupt()方法则会抛出InterruptedException异常从而允许你捕获这个异常并进行相应的处理。 // 可打断 Slf4j(topic c.Test3) public class Test3 {static ReentrantLock lock new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {log.debug(t1 running);try {lock.lockInterruptibly();} catch (InterruptedException e) {log.debug(t1:在等锁过程中被打断);e.printStackTrace();return;}try {log.debug(t1 获取锁 {}, System.currentTimeMillis());} finally {lock.unlock();}}, t1);lock.lock();log.debug(主线程获得锁);t1.start();try {sleep(1000);t1.interrupt(); // 打断t1log.debug(执行打断);} finally {log.debug(主线程释放锁);lock.unlock();}} }不可打断  在ReentrantLock中默认的锁获取方法lock()是不可中断的。这意味着如果一个线程尝试获取一个已经被其他线程持有的锁它将会一直阻塞直到成功获取到锁即使这个线程在这期间被中断即调用了该线程的interrupt()方法也不会抛出InterruptedException而是继续等待直至获得锁。这种行为可以被视为“不可打断”。 // 不可打断 Slf4j(topic c.Test4) public class Test4 {static ReentrantLock lock new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {log.debug(t1 启动 {}, System.currentTimeMillis());lock.lock();try {log.debug(t1 获得锁 {}, System.currentTimeMillis());} finally {log.debug(t1 释放锁 {}, System.currentTimeMillis());lock.unlock();}}, t1);lock.lock();log.debug(主线程获得锁 {}, System.currentTimeMillis());t1.start();try {log.debug(执行打断 {}, System.currentTimeMillis());sleep(1000);t1.interrupt();} finally {log.debug(主线程释放锁 {}, System.currentTimeMillis());lock.unlock();}} } 执行结果 10:18:41 [main] c.Test4 - 主线程获得锁 1742696321911 10:18:41 [main] c.Test4 - 执行打断 1742696321917 10:18:41 [t1] c.Test4 - t1 启动 1742696321917 10:18:42 [main] c.Test4 - 主线程释放锁 1742696322931 10:18:42 [t1] c.Test4 - t1 获得锁 1742696322931 10:18:42 [t1] c.Test4 - t1 释放锁 1742696322931 锁超时(tryLock) tryLock()尝试立即获取锁。如果锁当前没有被其他线程持有则该方法会成功获取锁并返回true如果锁已经被其他线程持有则该方法不会阻塞而是立刻返回false。tryLock(long timeout, TimeUnit unit)尝试在指定的时间内获取锁。如果在这个时间段内成功获取到了锁则返回true如果在这个时间段内未能获取到锁即锁一直被其他线程持有则返回false。此外如果在等待期间当前线程被中断它将抛出InterruptedException。 立刻返回 // 锁超时 --- 立刻返回 Slf4j(topic c.Test5) public class Test5 {static ReentrantLock lock new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {log.debug(t1 running);if (!lock.tryLock()) {log.debug(t1 获取锁失败, 立刻返回);return;}try {log.debug(t1 获得锁成功);} finally {lock.unlock();}}, t1);lock.lock();t1.start();try {sleep(1000);} finally {lock.unlock();}} }超时释放  Slf4j(topic c.Test5) public class Test6 {static ReentrantLock lock new ReentrantLock();public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(() - {log.debug(t1 running);try {// 超时释放if (!lock.tryLock(1, TimeUnit.SECONDS)) {log.debug(t1 1s尝试获得锁失败);return;}} catch (InterruptedException e) {e.printStackTrace();}try {log.debug(t1 获得锁成功);} finally {lock.unlock();}}, t1);lock.lock();t1.start();try {sleep(1500);} finally {log.debug(主线程释放锁);lock.unlock();}} }例子哲学家问题 Slf4j(topic c.Test7) public class Test7 {public static void main(String[] args) {ChopSticks c1 new ChopSticks(1);ChopSticks c2 new ChopSticks(2);ChopSticks c3 new ChopSticks(3);ChopSticks c4 new ChopSticks(4);ChopSticks c5 new ChopSticks(5);Philosopher p1 new Philosopher(p1, c1, c2);Philosopher p2 new Philosopher(p2, c2, c3);Philosopher p3 new Philosopher(p3, c3, c4);Philosopher p4 new Philosopher(p4, c4, c5);Philosopher p5 new Philosopher(p5, c5, c1);p1.start();p2.start();p3.start();p4.start();p5.start();} }class ChopSticks extends ReentrantLock {String name;public ChopSticks(String name) {this.name name;}Overridepublic String toString() {return 筷子{ name };} } Slf4j(topic c.Philosopher) class Philosopher extends Thread {ChopSticks left;ChopSticks right;public Philosopher(String name, ChopSticks left, ChopSticks right) {super(name);this.left left;this.right right;}public void eat(){log.debug({} eating, Thread.currentThread().getName());try {sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}Overridepublic void run() {while (true) {// 尝试获得左边的筷子if (left.tryLock()) {try {// 尝试获得右边的筷子if (right.tryLock()) {try {eat();} finally {right.unlock();}}} finally {left.unlock();}}}} }公平锁/非公平锁  非公平锁 定义在非公平锁机制下锁不会保证按照请求的先后顺序来分配。当锁可用时任何一个尝试获取锁的线程都有机会获得锁包括那些刚刚释放了这个锁并且立刻再次尝试获取它的线程。默认行为如果不特别指定ReentrantLock默认采用的是非公平锁策略即new ReentrantLock()等同于new ReentrantLock(false)。性能通常情况下非公平锁可以获得更高的吞吐量因为它减少了线程上下文切换的次数并且允许线程在锁刚被释放时迅速重新获取锁而不需要排队等待。 // 非公平锁 Slf4j(topic c.Test8) public class Test8 {static ReentrantLock lock new ReentrantLock(false);public static void main(String[] args) throws InterruptedException {for (int i 0; i 500; i ) {new Thread(() - {lock.lock();try {log.debug({} 获得锁成功, Thread.currentThread().getName());} finally {lock.unlock();}}, t i).start();}Thread.sleep(1);new Thread(()-{log.debug(start-----------------------);lock.lock();try {log.debug({} 获得锁成功 running, Thread.currentThread().getName());} finally {lock.unlock();}}, 强行抢夺).start();} }公平锁 定义当使用公平锁时锁会按照线程请求的顺序来分配。也就是说最早提出请求的线程将最先被授予锁。这有助于避免“饥饿”现象即某些线程永远无法获得锁。实现要创建一个公平锁的ReentrantLock实例可以在构造函数中传入参数true例如new ReentrantLock(true)。性能由于需要维护线程请求锁的顺序公平锁可能会导致较低的吞吐量。因为每当有线程释放锁后系统必须检查等待队列中的下一个线程是否可以获取锁而不是简单地允许当前正在尝试获取锁的线程直接获取它。 // 公平锁 Slf4j(topic c.Test8) public class Test8 {static ReentrantLock lock new ReentrantLock(true);public static void main(String[] args) throws InterruptedException {for (int i 0; i 500; i ) {new Thread(() - {lock.lock();try {log.debug({} 获得锁成功, Thread.currentThread().getName());} finally {lock.unlock();}}, t i).start();}Thread.sleep(1);new Thread(()-{log.debug(start-----------------------);lock.lock();try {log.debug({} 获得锁成功 running, Thread.currentThread().getName());} finally {lock.unlock();}}, 强行抢夺).start();} }await/Condition 等待条件await方法系列 当一个线程需要等待某个特定条件发生时可以调用Condition对象的await()方法进入等待状态。这会导致当前线程释放锁并等待直到另一个线程调用了同一个Condition对象的signal()或signalAll()方法。常见的await方法包括 await()使当前线程进入等待状态直到被通知或中断。awaitUninterruptibly()类似于await()但是不会响应中断。awaitNanos(long nanosTimeout)尝试等待指定的时间长度如果超时则返回剩余时间。awaitUntil(Date deadline)等待直到指定的时间点如果到达截止时间还未被通知则继续执行。 通知条件signal方法系列 当一个线程修改了共享资源并且认为可能满足了一个或多个正在等待的线程的条件时它可以调用Condition对象的signal()或signalAll()方法来唤醒等待的线程。 signal()唤醒一个等待此Condition的线程。如果有多个线程在等待则选择其中的一个进行唤醒。signalAll()唤醒所有等待此Condition的线程。 可以把Condition实例看作对应的等待队列不同的线程可以调用不同的等待队列的await方法使得当前线程进入当前的等待队列中  ​ // 等待队列 Condition实例 // 唤醒线程signal或signalAll Slf4j(topic c.Test9) public class Test9 {static ReentrantLock lock new ReentrantLock();static Condition waitBreadQueue lock.newCondition();static Condition waitCoffeeQueue lock.newCondition();static volatile boolean hasBread false;static volatile boolean hasCoffee false;public static void main(String[] args) throws InterruptedException {new Thread(() - {try {lock.lock();while (!hasCoffee) {try {log.debug(等待咖啡);waitCoffeeQueue.await(); // 等咖啡队列} catch (InterruptedException e) {e.printStackTrace();}}log.debug(t1 收到咖啡);} finally {log.debug(t1 释放锁);lock.unlock();}}, t1).start();new Thread(() - {try {lock.lock();while (!hasBread) {try {log.debug(等待面包);waitBreadQueue.await(); // 等面包队列} catch (InterruptedException e) {e.printStackTrace();}}log.debug(t2 收到面包);} finally {log.debug(t2 释放锁);lock.unlock();}}, t2).start();sleep(1000);handleCoffee();sleep(1000);handleBread();}public static void handleCoffee() {lock.lock();try {log.debug(发咖啡);hasCoffee true;waitCoffeeQueue.signal(); // 唤醒等待咖啡的线程} finally {lock.unlock();}}public static void handleBread() {lock.lock();try {log.debug(发面包);hasBread true;waitBreadQueue.signal(); // 唤醒等待面包的线程} finally {lock.unlock();}} }​ 如有错误欢迎指正  图源来自网络侵删
http://www.pierceye.com/news/141238/

相关文章:

  • 郑州网站建设哪家有什么可以做兼职的网站吗
  • 没有影视许可怎么用国内空间做网站wordpress首页加广告代码
  • 高端电子商务网站建设js网页特效案例
  • 一个网站做三个关键词网站的建设与维护的职责
  • wordpress tag伪静态网站建设与优化推广方案模板
  • 公司网站建设 宁波传奇网站模板psd
  • 安县移动网站建设广州 网站制作
  • 山西太原网站建设网站设计计划
  • 广州番禺网站制作推广新浦网站制作
  • 做网站你给推广怎么仿制别人的网站
  • 做离心开关的企业的网站韩国女足出线了吗
  • 毕业设计网站开发题目shop++是什么
  • fqapps com网站怎么做wordpress慢数据库
  • 青岛制作网站企业安徽seo报价
  • 潍坊市高新区建设局网站hdsyscms企业建站系统
  • 网站运营做产品需要哪些知识开启wordpress多站点
  • flash网站源码 免费怎么可以自己制作网站
  • wordpress文章站主题如何删除自己建的网站
  • 徐州网站建设哪家好薇深圳找工作的网站
  • 局域网站点建设方案东莞企业营销型网站
  • 中国光大国际建设工程公司网站自己开店
  • 手机建站程序昆山设计公司
  • 网站泛解析中国新闻社是国企还是私企
  • dw做静态网站手机app制作视频教程
  • 惠州做网站公司网页游戏排行榜前十名歌
  • 会ps的如何做网站高等教材建筑电气久久建筑网
  • 甘肃住房城乡建设厅网站wordpress风格化页面
  • 起名网站建设免费找素材软件
  • 网站基本信息设置链接搜索
  • 广州海珠网站开发营销策划