打字猴:1.700451403e+09
1700451403
1700451404 a.a1(b);
1700451405
1700451406 }
1700451407
1700451408 },“线程A”).start();
1700451409
1700451410 //线程B
1700451411
1700451412 new Thread(new Runnable(){
1700451413
1700451414 public void run(){
1700451415
1700451416 b.b1(a);
1700451417
1700451418 }
1700451419
1700451420 },“线程B”).start();
1700451421
1700451422 }
1700451423
1700451424 此段程序定义了两个资源A和B,然后在两个线程A、B中使用了该资源,由于两个资源之间有交互操作,并且都是同步方法,因此在线程A休眠1秒钟后,它会试图访问资源B的b2方法,但是线程B持有该类的锁,并同时在等待A线程释放其锁资源,所以此时就出现了两个线程在互相等待释放资源的情况,也就是死锁了,运行结果如下:
1700451425
1700451426 线程A进入A.a1()
1700451427
1700451428 线程B进入B.b1()
1700451429
1700451430 线程B试图访问A.a2()
1700451431
1700451432 线程A试图访问B.b2()
1700451433
1700451434 此种情况下,线程A和线程B会一直互等下去,直到有外界干扰为止,比如终止一个线程,或者某一线程自行放弃资源的争抢,否则这两个线程就始终处于死锁状态了。我们知道要达到线程死锁需要四个条件:
1700451435
1700451436 互斥条件:一个资源每次只能被一个线程使用。
1700451437
1700451438 资源独占条件:一个线程因请求资源而阻塞时,对已获得的资源保持不放。
1700451439
1700451440 不剥夺条件:线程已获得的资源在未使用完之前,不能强行剥夺。
1700451441
1700451442 循环等待条件:若干线程之间形成一种头尾相接的循环等待资源关系。
1700451443
1700451444 只有满足了这些条件才可能产生线程死锁,这也同时告诫我们如果要解决线程死锁问题,就必须从这四个条件入手,一般情况下可以按照以下两种方式来解决:
1700451445
1700451446 (1)避免或减少资源共享
1700451447
1700451448 一个资源被多个线程共享,若采用了同步机制,则产生的死锁可能性很大,特别是在项目比较庞大的情况下,很难杜绝死锁,对此最好的解决办法就是减少资源共享。
1700451449
1700451450 例如一个B/S结构的办公系统可以完全忽略资源共享,这是因为此类系统有三个特征:一是并发访问不会太高,二是读操作多于写操作,三是数据质量要求比较低,因此即使出现数据资源不同步的情况也不可能产生太大的影响,完全可以不使用同步技术。但是如果是一个支付清算系统就必须慎重考虑资源同步问题了,因为此类系统一是数据质量要求非常高(如果产生数据不同步的情况那可是重大生产事故),二是并发量大,不设置数据同步则会产生非常多的运算逻辑失效的情况,这会导致交易失败,产生大量的“脏”数据,系统可靠性将大大降低。
1700451451
1700451452 (2)使用自旋锁
[ 上一页 ]  [ :1.700451403e+09 ]  [ 下一页 ]