线程安全概念:当多个线程访问某个类(对象或方法)时 , 这个类始终能表现出正确的行为 , 那么这个类(对象或方法)就是线程安全的。
线程不安全:
1 package com.itdoc.multi.sync001; 2 3 /** 4 * @author Wáng Chéng Dá 5 * @create 2017-03-20 7:53 6 */ 7 public class MyThread extends Thread { 8 9 public int count = 5; 10 @Override 11 public void run() { 12 count--; 13 System.out.println(this.currentThread().getName() + " : count = " + count); 14 } 15 16 public static void main(String[] args) { 17 MyThread myThread = new MyThread(); 18 Thread t1 = new Thread(myThread, "t1"); 19 Thread t2 = new Thread(myThread, "t2"); 20 Thread t3 = new Thread(myThread, "t3"); 21 Thread t4 = new Thread(myThread, "t4"); 22 Thread t5 = new Thread(myThread, "t5"); 23 t1.start(); 24 t2.start(); 25 t3.start(); 26 t4.start(); 27 t5.start(); 28 } 29 }
控制台输出:
t2 : count = 3 |
分析:因为线程不安全 , 在一个线程没有完成时 , 另一个线程也可以进入相同的方法 , 所以控制台打印输出会有不确定性。
线程安全:
1 package com.itdoc.multi.sync001; 2 3 /** 4 * 线程安全概念:当多个线程访问某一个类 (对象或方法) 时, 这个类 (对象或方法)始终都能表现出正确的行为, 5 * 那么这个类 (对象或方法) 就是线程安全的。 6 * synchronized:可以在任意对象及方法上加锁, 而加锁的这段代码称为:"互斥区", "临界区"。 7 * 8 * @author Wáng Chéng Dá 9 * @create 2017-03-20 7:53 10 */ 11 public class MyThread extends Thread { 12 13 public int count = 5; 14 @Override 15 public synchronized void run() { 16 count--; 17 System.out.println(this.currentThread().getName() + " : count = " + count); 18 } 19 20 public static void main(String[] args) { 21 /** 22 * 分析: 当多个线程访问 myThread 的 run 方法时, 以排队的方式进行处理。 23 * 24 * 一个线程若要调用 synchronized 修饰的方法中代码: 25 * 1.尝试获取锁。 26 * 2.若获取到锁, 执行 synchronized 修饰的方法中的代码。 27 * 若没有获取到锁, 会不断尝试获取锁直到获取为止,而且过个线程会相互竞争这把锁。 28 */ 29 MyThread myThread = new MyThread(); 30 Thread t1 = new Thread(myThread, "t1"); 31 Thread t2 = new Thread(myThread, "t2"); 32 Thread t3 = new Thread(myThread, "t3"); 33 Thread t4 = new Thread(myThread, "t4"); 34 Thread t5 = new Thread(myThread, "t5"); 35 t1.start(); 36 t2.start(); 37 t3.start(); 38 t4.start(); 39 t5.start(); 40 } 41 }
控制台输出:
t1 : count = 4 |
分析:多个线程访问 synchronized 修饰的方法时 , 若一个线程先获取锁 , 只有这个线程执行完这段代码 , 释放锁之后 , 其余线程才可以获取到这把锁 , 他们是相互竞争关系。循环这种方式 , 直到所有线程执行结束。