Java多线程分析(八)----Syschronized VS ReentrankLock

1.Synchronized Vs ReentrantLock 的区别:在低并发量时期两者性能没有较大的区别,在高并发量的情况下,Sync的阻塞性的锁会严重的损害其性能

  在Java1.5之前写并发程序的时候,Synchronized对多个线程共享共同的资源变量中为了保证其共享资源的线程安全的性能,采用Synchronized对共享资源表持同步机制,但是这种同步机制提供的锁是一种悲观锁,在任何的时候只有一个线程才能够进入临界区域,对其他的线程产生一种阻塞的状态,如果一步注意的话,一般有可能会产生死锁的状态(线程永远处在等待的状态,一种十分糟糕的情况)。将这种锁叫做是内置锁,缺点:内置锁在执行的过程中无法被中断。Synchronized 关键词锁住的只能是某个对象,或者是某个方法,不能锁住某个变量,LOck可以锁住中某个变量,Synchronized对某些线程不安全的方法,直接在这种方法外进行锁的封装。通过增加这个关键词,将不是很安全线程进行线程安全操作

下面模拟火车站买票的情况,总的票数AllTotal,分为三个窗口售票,采用Synchronized这个内置锁的关键字进行模拟操作。

  Sync锁一般要么锁住方法或者锁住同步码块,在这里锁住代码块,最好采用锁住同步码块减少锁的力度,有利于系统操作

 1 package ExecutorDemoPagage;
 2
 3 public class TranDemo implements Runnable{
 4     public static int AllTotal=20;
 5     public static int i=1;
 6     public static Object obj=new Object();
 7     public void run()
 8     {//在售票的过程中,每个窗口可以同时访问主票数
 9         while(true)
10         {
11          //System.out.println(Thread.currentThread().getName()+"窗口开始进行售票");
12             //sync关键锁住必须要是一个对象,或者一个方法
13             synchronized(this){
14               if(AllTotal>0)//将此放入锁之内,因为,必须要锁住这个代码
15               {
16                           try {
17                         Thread.sleep(200);
18                     } catch (InterruptedException e) {
19                         // TODO Auto-generated catch block
20                         e.printStackTrace();
21                     }
22                           System.out.println(Thread.currentThread().getName()+"窗口售票出第"+i+++"票");
23                           AllTotal=AllTotal-1;
24
25               }
26               else
27               {
28                   break;
29               }
30           }
31         }
32     }
33
34     public static void main(String[] args) {
35         // TODO Auto-generated method stub
36         //采用5个线程进行模拟表示的是5个窗口,直到所有的票多卖完
37         TranDemo T=new TranDemo();
38         Thread [] t= new Thread[5];
39         for (int i=0;i<5;i++)
40         {
41             t[i]=new Thread(T);//
42             t[i].start();
43
44         }
45     }
46
47 }

结果显示:

  Java中ReentrantLock为我们重入锁的概念是一种乐观锁,采用CAS的原子性操作,能够实现非阻塞类结构的算法,同时能够与异常进行交互式操作。这种锁显示锁,必须要人工的进行解锁操作,但是synchronized自动的进行解锁。

总结:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。最重要的一点,每一次在使用锁的过程中必须保证这把锁是解锁状态,特别在while,for循环中,UNLock写入到循环中这样才能保证此线程在循环过程对共享资源进行操作,这也是为什么叫可重入锁的原因。

  同样一个采用ReentrantLock:模拟火车票的购票情况:

  

 1 package ExecutorDemoPagage;
 2
 3 import java.util.concurrent.locks.ReentrantLock;
 4
 5 public class TranDemo1 implements Runnable  {
 6     public static int AllTotal=20;
 7     public static int i=0;
 8     //多个线程采用同一把锁
 9     public static ReentrantLock lock1=new ReentrantLock();
10
11     public void run()
12     {
13         while(true)
14         {
15             try{
16                 lock1.lock();
17                 if (AllTotal>0)
18                 {
19                     System.out.println(Thread.currentThread().getName()+"窗口售票出第"+i+++"票");
20                     AllTotal=AllTotal--;
21                 }
22             }finally{
23                 lock1.unlock();
24             }
25             if(AllTotal<=0)
26             {
27                 break;
28             }
29         }
30     }
31
32     public static void main(String[] args) {
33         // TODO Auto-generated method stub
34         //采用5个线程进行模拟表示的是5个窗口,直到所有的票多卖完
35         TranDemo T=new TranDemo();
36         Thread [] t= new Thread[5];
37         for (int i=0;i<5;i++)
38         {
39             t[i]=new Thread(T);//
40             t[i].start();
41
42         }
43     }
44 }

1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

  2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

  3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

  4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

  5)Lock可以提高多个线程进行读操作的效率。

  在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

2.Synchronized与ReentrantLock相比,如果在线程中发生了死锁的情况,对于Sync锁而言导致两个线程一直处于中断,对于ReentrantLock可以采用Lock.LockInterruptibly()对这种死锁的情况进行可中断的处理,抛出异常,让人理解,同时可以采用ReentrantLock中可实现的方法来避免中断。

  下面通过模拟死锁的对其可中断的情况进行处理:

 1 package JavaLockPackage;
 2
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 import java.util.concurrent.locks.ReentrantLock;
 6
 7 //在这个过程中模拟死锁的过程
 8 public class ReentrantLockInt implements Runnable{
 9     //开辟连个锁,在开始的时候锁住1线程,其中锁住2线程,在2线程过程中锁住1线程
10     public  int lock;
11     public static ReentrantLock lock1=new ReentrantLock();
12     public static ReentrantLock lock2=new ReentrantLock();
13     public ReentrantLockInt(int L)
14     {
15         this.lock=L;
16     }
17     public void run()
18     {try{
19         if(lock==1)
20         {  lock1.lockInterruptibly();
21             //开始锁定线程1
22             try {
23                 Thread.sleep(100);
24             } catch (InterruptedException e) {
25                 // TODO Auto-generated catch block
26                 e.printStackTrace();
27             }
28             lock2.lockInterruptibly();//只能够用这个方法,普通的lock无用的,
29                                     //因为lock2在线程2中没有解锁,所以在此发生死锁的情况
30         }
31         else
32         {
33             lock2.lockInterruptibly();
34             try {
35                 Thread.sleep(100);
36             } catch (InterruptedException e) {
37                 // TODO Auto-generated catch block
38                 e.printStackTrace();
39             }
40             lock1.lockInterruptibly();//只能够用这个方法,普通的lock无用的
41         }
42      }catch(InterruptedException e)
43         {
44             e.printStackTrace();
45         }
46     finally{
47         if(lock1.isHeldByCurrentThread())//或者采用lock1.getHoldCount(1)判断是否得到锁
48         {
49             lock1.unlock();
50         }
51         if(lock2.isHeldByCurrentThread())
52         {
53             lock2.unlock();
54         }
55         System.out.println(Thread.currentThread().getId()+"线程退出");
56     }
57     }
58     public static void main(String[] args) throws InterruptedException {
59         // TODO Auto-generated method stub
60         Thread t1=new Thread(new ReentrantLockInt(1));
61         Thread t2=new Thread(new ReentrantLockInt(2));
62         t1.start();t2.start();
63         Thread.sleep(1000);
64         DeadlockChecker.check();//这里必须要有一个死锁检查程序,不然使用中断的无法进行结束。
65     }
66
67 }
 1 package JavaLockPackage;
 2
 3 import java.lang.management.ManagementFactory;
 4 import java.lang.management.ThreadInfo;
 5 import java.lang.management.ThreadMXBean;
 6
 7 //此程序最主要对死锁过程中的锁进行检查
 8 public class DeadLockCheck {
 9     private final static ThreadMXBean mbean=ManagementFactory.getThreadMXBean();
10     //此功能是对CPU的运行时间和竞争征用进行监视,评估某个线程运行的时间
11     final static Runnable deadLockChecker=new Runnable(){
12         public void run()
13         { while(true)
14           {//通过ThreadMXBean找到所有死锁中断程序,与输入程序的线程ThreadInfo进行比较,Id相同则进行中断
15             long [] deadlockedThreadIds=mbean.findDeadlockedThreads();
16             if(deadlockedThreadIds!=null){
17                 ThreadInfo [] threadInfos=mbean.getThreadInfo(deadlockedThreadIds);
18                 for(Thread t:Thread.getAllStackTraces().keySet())
19                 {
20                     for(int i=0;i<threadInfos.length;i++)
21                     {
22                         if(t.getId()==threadInfos[i].getThreadId())
23                         {
24                             t.interrupt();
25                         }
26                     }
27                 }
28             }
29             try{
30                 Thread.sleep(500);
31             }catch(InterruptedException e)
32             {
33                 e.printStackTrace();
34             }
35           }
36
37         }
38     };
39     public static void check()
40     {
41         Thread t=new Thread(deadLockChecker);//传替一种方法
42         t.setDaemon(true);
43         t.start();
44     }
45 }

通过jps,jstack来查看系统中虚拟机的运行情况:

第二种避免死锁的情况而已进行可现实,使用lock.tryLock()方法,这样,不需要直接写其中断的方法

 1 package JavaLockPackage;
 2
 3 import java.util.concurrent.TimeUnit;
 4 import java.util.concurrent.locks.ReentrantLock;
 5
 6 public class TimeLock implements Runnable {
 7     public static ReentrantLock lock=new ReentrantLock();
 8     public void run()
 9     {
10         try{
11             if(lock.tryLock(5,TimeUnit.SECONDS ))//在规定的时间中竞争同一把锁
12                 {
13                   System.out.println(Thread.currentThread().getName()+"Get Successed Lock");
14                   Thread.sleep(5000);
15                 }
16             else
17             {
18                 System.out.println(Thread.currentThread().getName()+"Get Failed Lock");
19             }
20         }    catch(InterruptedException e)
21         {
22             e.printStackTrace();
23         }
24
25         finally
26         {
27             if(lock.isHeldByCurrentThread())
28                 lock.unlock();
29         }
30     }
31     public static void main(String[] args) {
32         // TODO Auto-generated method stub
33             TimeLock L1=new TimeLock();
34             Thread p1=new Thread(L1);
35             Thread p2=new Thread(L1);
36             //俩个线程竞争同一把锁
37             p1.start();p2.start();
38
39     }
40
41 }

结果显示:第一种结果:

第二种结果:

3.练习题:

问题的描述

启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13,14,15. 接着再由线程1打印16,17,18,19,20....以此类推, 直到打印到75. 程序的输出结果应该为:

线程1: 1

线程1: 2

线程1: 3

线程1: 4

线程1: 5

线程2: 6

线程2: 7

线程2: 8

线程2: 9

线程2: 10

...

线程3: 71

线程3: 72

线程3: 73

线程3: 74

线程3: 75

第一种方法,采用Synchronized,notify(),wait()

  1 package ThreadTest;
  2 //用这种方法不在main函数中将pn写成全局变量这样导致id,id1,id2值发生修改
  3 public class NUmbelPrint implements Runnable{
  4 static int state=1;
  5 static int n=1;
  6 private int id=0,id1=0,id2=0;
  7   static NUmbelPrint pn=new NUmbelPrint();
  8     public static void main(String[] args) {
  9         // TODO Auto-generated method stub
 10             pn.id=1;new Thread(pn).start();try {
 11                 Thread.sleep(20);
 12             } catch (InterruptedException e) {
 13                 // TODO Auto-generated catch block
 14                 e.printStackTrace();
 15             }
 16             pn.id=0;pn.id1=2;new Thread(pn).start();
 17             try{
 18             Thread.sleep(20);
 19            } catch (InterruptedException e) {
 20         // TODO Auto-generated catch block
 21         e.printStackTrace();
 22     }
 23         pn.id1=0;pn.id=0;pn.id2=3;new Thread(pn).start();
 24         try{
 25             Thread.sleep(20);
 26            } catch (InterruptedException e) {
 27         // TODO Auto-generated catch block
 28         e.printStackTrace();
 29     }
 30
 31     }
 32     public void run()
 33     {    if(id==1)
 34         work(id);
 35         if(id1==2)
 36         work1(id1);
 37         if(id2==3)
 38         work2(id2);
 39     }
 40     public void work(int temp){
 41         for(int i=0;i<5;i++)
 42         {
 43                 synchronized (pn){
 44                     while(state !=temp)
 45                     {
 46                         try {
 47                             this.wait();
 48                         } catch (InterruptedException e) {
 49                             // TODO Auto-generated catch block
 50                             e.printStackTrace();
 51                         }
 52                     }
 53                     for(int j=0;j<5;j++)
 54                     {
 55                         System.out.println(Thread.currentThread().getName()+"线程 "+n++);
 56                     }
 57                     state=2;
 58                     pn.notifyAll();
 59                     if(i==4)
 60                         System.out.println("线程1"+state);
 61                 }
 62         }
 63     }
 64     public void work1(int temp){
 65         for(int i=0;i<=5;i++){
 66             synchronized (pn){
 67                 while(state !=temp)
 68                 {
 69                     try {
 70                         this.wait();
 71                     } catch (InterruptedException e) {
 72                         // TODO Auto-generated catch block
 73                         e.printStackTrace();
 74                     }
 75                 }
 76                 for(int j=0;j<5;j++)
 77                 {
 78                     System.out.println(Thread.currentThread().getName()+"线程 "+n++);
 79                 }
 80                 state=3;
 81                 pn.notifyAll();
 82             }
 83             if(i==4)
 84                 System.out.println("线程2"+state);
 85         }
 86     }
 87     public void work2(int temp){
 88         for(int i=0;i<5;i++){//第三个线程运行了4次
 89                 synchronized (pn){
 90                     while(state !=temp)
 91                     {
 92                         try {
 93                             this.wait();
 94                         } catch (InterruptedException e) {
 95                             // TODO Auto-generated catch block
 96                             e.printStackTrace();
 97                         }
 98                     }
 99                     for(int j=0;j<5;j++)
100                     {
101                         System.out.println(Thread.currentThread().getName()+"线程 "+n++);
102                     }
103                     state=1;
104                     pn.notifyAll();
105                 }
106
107                     System.out.println("线程3--"+state+"---"+i);
108         }
109     }
110 }
111 //为什么最后一次中会0 1 0,因为线程1结束后就没有了,在整个程序中只有俩个线程,所以1 2 3修改成1 2,现在只有两个线程
112 //在这里竞争,所以最后才会出现0 1 0,线程发生变化
 1 public class NumberPrintDemo {
 2     // n为即将打印的数字,这里采用的匿名类部类的方法:
 3     private static int n = 1;
 4     // state=1表示将由线程1打印数字, state=2表示将由线程2打印数字, state=3表示将由线程3打印数字
 5     private static int state = 1;
 6
 7     public static void main(String[] args) {
 8         final NumberPrintDemo pn = new NumberPrintDemo();
 9         new Thread(new Runnable() {
10             public void run() {
11                 // 3个线程打印75个数字, 单个线程每次打印5个连续数字, 因此每个线程只需执行5次打印任务. 3*5*5=75
12                 for (int i = 0; i < 5; i++) {
13                     // 3个线程都使用pn对象做锁, 以保证每个交替期间只有一个线程在打印
14                     synchronized (pn) {
15                         // 如果state!=1, 说明此时尚未轮到线程1打印, 线程1将调用pn的wait()方法, 直到下次被唤醒
16                         while (state != 1)
17                             try {
18                                 pn.wait();
19                             } catch (InterruptedException e) {
20                                 e.printStackTrace();
21                             }
22                         // 当state=1时, 轮到线程1打印5次数字
23                         for (int j = 0; j < 5; j++) {
24                             // 打印一次后n自增
25                             System.out.println(Thread.currentThread().getName()
26                                     + ": " + n++);
27                         }
28                         System.out.println();
29                         // 线程1打印完成后, 将state赋值为2, 表示接下来将轮到线程2打印
30                         state = 2;
31                         // notifyAll()方法唤醒在pn上wait的线程2和线程3, 同时线程1将退出同步代码块, 释放pn锁.
32                         // 因此3个线程将再次竞争pn锁
33                         // 假如线程1或线程3竞争到资源, 由于state不为1或3, 线程1或线程3将很快再次wait, 释放出刚到手的pn锁.
34                         // 只有线程2可以通过state判定, 所以线程2一定是执行下次打印任务的线程.
35                         // 对于线程2来说, 获得锁的道路也许是曲折的, 但前途一定是光明的.
36                         pn.notifyAll();
37                     }
38                 }
39             }
40         }, "线程1").start();
41
42         new Thread(new Runnable() {
43             public void run() {
44                 for (int i = 0; i < 5; i++) {
45                     synchronized (pn) {
46                         while (state != 2)
47                             try {
48                                 pn.wait();
49                             } catch (InterruptedException e) {
50                                 e.printStackTrace();
51                             }
52                         for (int j = 0; j < 5; j++) {
53                             System.out.println(Thread.currentThread().getName()
54                                     + ": " + n++);
55                         }
56                         System.out.println();
57                         state = 3;
58                         pn.notifyAll();
59                     }
60                 }
61             }
62         }, "线程2").start();
63
64         new Thread(new Runnable() {
65             public void run() {
66                 for (int i = 0; i < 5; i++) {
67                     synchronized (pn) {
68                         while (state != 3)
69                             try {
70                                 pn.wait();
71                             } catch (InterruptedException e) {
72                                 e.printStackTrace();
73                             }
74                         for (int j = 0; j < 5; j++) {
75                             System.out.println(Thread.currentThread().getName()
76                                     + ": " + n++);
77                         }
78                         System.out.println();
79                         state = 1;
80                         pn.notifyAll();
81                     }
82                 }
83             }
84         }, "线程3").start();
85     }
86 }

第二种:ReentrantLock,await(),signal()

  1 package JavaLockPackage;
  2
  3 import java.util.concurrent.locks.Condition;
  4 import java.util.concurrent.locks.ReentrantLock;
  5
  6 //三个线程轮换打印12345 678910,。。。。。有序的打印直到75
  7 public class LockAndConditionExam  {
  8     private static int n=1;
  9     private static int state=1;
 10
 11     private static ReentrantLock lock1=new ReentrantLock();
 12     //获取其中的三个分支线程
 13     private static Condition c1=lock1.newCondition();
 14     private static Condition c2=lock1.newCondition();
 15     private static Condition c3=lock1.newCondition();
 16     //的是一个实例,必须要加上static关键字,不然会成为class类,
 17     private static class CreateThread1 implements Runnable{
 18         public void run()
 19         {
 20             for(int i=0;i<5;i++)
 21             {    try{
 22                 lock1.lock();
 23                 while(state!=1)
 24                 {
 25                     try{
 26                         c1.await();
 27
 28                     }
 29                     catch(InterruptedException e)
 30                     {
 31                         e.printStackTrace();
 32                     }
 33                 }
 34                 for(int j=0;j<5;j++)
 35                 {
 36                     System.out.println(Thread.currentThread().getName()+"-线程--"+n++);
 37                 }
 38                  System.out.println();
 39                  state=2;
 40                 c2.signal();
 41
 42             }
 43             finally{
 44                 lock1.unlock();
 45             }
 46
 47             }
 48         }
 49     }
 50
 51     private static class CreateThread2 implements Runnable{
 52         public void run()
 53         {
 54             for(int i=0;i<5;i++)
 55             {    try{
 56                 lock1.lock();
 57                 while(state!=2)
 58                 {
 59                     try{
 60                         c2.await();
 61
 62                     }
 63                     catch(InterruptedException e)
 64                     {
 65                         e.printStackTrace();
 66                     }
 67                 }
 68                 for(int j=0;j<5;j++)
 69                 {
 70                     System.out.println(Thread.currentThread().getName()+"-线程--"+n++);
 71                 }
 72                  System.out.println();
 73                  state=3;
 74                 c3.signal();
 75
 76             }
 77             finally{
 78                 lock1.unlock();
 79             }
 80
 81             }
 82         }
 83     }
 84
 85     private static class CreateThread3 implements Runnable{
 86         public void run()
 87         {
 88             for(int i=0;i<5;i++)
 89             {    try{
 90                 lock1.lock();
 91                 while(state!=3)
 92                 {
 93                     try{
 94                         c3.await();
 95
 96                     }
 97                     catch(InterruptedException e)
 98                     {
 99                         e.printStackTrace();
100                     }
101                 }
102                 for(int j=0;j<5;j++)
103                 {
104                     System.out.println(Thread.currentThread().getName()+"-线程--"+n++);
105                 }
106                  System.out.println();
107                  state=1;
108                 c1.signal();
109
110             }
111             finally{
112                 lock1.unlock();
113             }
114
115             }
116         }
117     }
118     public static void main(String[] args) {
119         // TODO Auto-generated method stub
120
121             //对run方法进行重载
122            Thread T1=new Thread (){
123
124                public void run()
125                 {
126                     for(int i=0;i<5;i++)
127                     {    try{
128                         lock1.lock();
129                         while(state!=1)
130                         {
131                             try{
132                                 c1.await();
133
134                             }
135                             catch(InterruptedException e)
136                             {
137                                 e.printStackTrace();
138                             }
139                         }
140                         for(int j=0;j<5;j++)
141                         {
142                             System.out.println(Thread.currentThread().getName()+"-线程--"+n++);
143                         }
144                          System.out.println();
145                          state=2;
146                         c2.signal();
147
148                     }
149                     finally{
150                         lock1.unlock();
151                     }
152
153                     }
154                 }
155                    };
156             T1.start();
157
158             Thread T2=new Thread(new CreateThread2());
159             T2.start();//方法是进行new Runnable 实例
160
161             Thread T3=new Thread(new CreateThread3());
162             T3.start();
163
164     }
165
166 }
时间: 2024-10-12 08:37:32

Java多线程分析(八)----Syschronized VS ReentrankLock的相关文章

Java 多线程(八) 线程状态图

结合多线程的学习过程,介绍线程的状态图,随着学习的深入,这幅图不断加入新的内容. 一.线程基本状态图 这幅图是在Java 多线程(三) 线程的生命周期及优先级出现过的: 图中是线程运行的基本状态:线程调用start()方法开始后,就进入到可运行状态,随着CPU的资源调度在运行和可运行之间切换:遇到阻塞则进入阻塞状态. 二.加入同步的线程状态图 多线程的同步机制,及synchronized关键字的使用学习: Java 多线程(五) 多线程的同步 Java 多线程(六) synchronized关键

Java多线程分析案例

1. 多线程的创建方式 (1).继承 Thread类:但Thread本质上也是实现了Runnable 接口的一个实例,它代表一个线程的实例,并且,启动线程的唯一方法就是通过 Thread 类的 start()实例方法.start()方法是一个 native 方法,它将启动一个新线程,并执行run()方法.这种方式实现多线程很简单,通过自己的类直接extend Thread,并复写run()方法,就可以启动新线程并执行自己定义的run()方法.例如:继承Thread类实现多线程,并在合适的地方启动

Java多线程系列八——volatile和ThreadLocal

参考资料: http://ifeve.com/java-memory-model-4/ http://www.infoq.com/cn/articles/java-memory-model-1 http://wuchong.me/blog/2014/08/28/how-to-correctly-write-singleton-pattern/ https://en.wikipedia.org/wiki/Singleton_pattern#Java_5_solution https://www.i

Java多线程(八)——join()

一.join()介绍 join() 定义在Thread.java中.join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行.这句话可能有点晦涩,我们还是通过例子去理解: // 主线程 public class Father extends Thread { public void run() { Son s = new Son(); s.start(); s.join(); ... } } // 子线程 public class Son extends Thread { publi

java多线程 -- 线程八锁

一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些synchronized方法锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法 加个普通方法后发现和同步锁无关 换成两个对象后,不是同一把锁了,情况立刻变化. 都换成静态同步方法后,情况又变化 所有的非静态同步方法用的都是同一把锁--实例对象本身,也

Java 多线程分析(七)----CAS操作和阻塞

1.原子性的操作: CAS --CompareAndSwap(),指的是多个线程进入临界区域中,让多个线程在临界区域上自由的竞争,最后能够保证有一个线程能够胜出,其他没有竞争到的线程可以再一次尝试.最终临界区域上的所有线程都能够线程安全性的完成,这种方式,也叫无锁的方式,在之前的Synchronized中,不允许其他线程进入到临界区域中去进行工作.无锁的方式只能够保证线程的安全性,不同于之前讲的同步机制,因此无法对线程进行有序的调度.CAS编程最主要特色:不需要采用锁的方式对共享的资源(受保护数

JAVA多线程(八)模式-Read Write Lock

Read Write Lock 写入是互斥的,读取是共享的,写入与读取不能同时发生. 适用环境 类似缓存更新的场景. 样例 缓存,多读多写,LRU淘汰. 读写锁 读读共享,读写.写写互斥. package ReadWriteLock; public class ReadWriteLock { private int waitWriters=0; private int writingWriters=0; private int readers=0; //读写都在等待时,写优先,读线程多,写线程少

java多线程(八)为什么弃用stop和suspend

转载请注明出处:http://blog.csdn.net/xingjiarong/article/details/47984659 初始的java版本中定义了一个stop方法来终止一个线程还定义了一个suspend方法来阻塞一个线程,直到另一个线程调用resume方法.这两个方法在Java SE 1.2之后就被弃用了,因为这两种方法都不安全,下面我们分别来讨论一下为什么不安全和应该怎样做才是安全的. 一.stop方法为什么不安全 其实stop方法天生就不安全,因为它在终止一个线程时会强制中断线程

Java多线程系列

参考资料: http://www.jianshu.com/p/40d4c7aebd66 0.环境 Java: jdk1.8.0_91 CPU: Intel Core i5-6500 Memory: 8G 1.说明 本系列文章为Java多线程的学习记录 Java多线程系列一--Java实现线程方法 Java多线程系列二--Thread类的方法 Java多线程系列三--实现线程同步的方法 Java多线程系列四--控制线程执行顺序 Java多线程系列五--列表类 Java多线程系列六--Map实现类