java多线程同步
用卖票演示同步代码块
1 package javase; 2 3 class Ticket implements Runnable{ 4 5 private int num = 100; 6 7 private Object obj = new Object(); 8 9 public void run() { 10 11 show(); 12 } 13 14 public void show() { 15 16 while(true) { 17 18 try { 19 Thread.sleep(10); 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 } 23 synchronized (obj) { 24 25 if(num>0) 26 System.out.println(Thread.currentThread().getName()+" ticket="+num--); 27 } 28 } 29 30 } 31 32 } 33 34 public class ThreadDemo2 { 35 36 public static void main(String[] args) { 37 38 Ticket t = new Ticket(); 39 40 Thread t1 = new Thread(t); 41 Thread t2 = new Thread(t); 42 Thread t3 = new Thread(t); 43 44 t1.start(); 45 t2.start(); 46 t3.start(); 47 48 } 49 50 }
创建三个线程对一个对象执行任务,即共用一个数据域。在执行 while(num>0)语句时,假设此时num=1,线程1进入并暂停运行。而此时num=1,线程2进入执行 num--,使得num=0输出打印。当线程1执行时,已经通过while语句的判断了,直接执行 num-- 输出打印,从而打印了0,出现错误。
使用线程同步块,在synchronized语句中只有一个线程进入,此时synchronized会给出判断结果,阻挡其他线程进入synchronized下的代码块,也就使得while语句每次都能执行完,避免错误。
演示同步函数
1 class Tickets implements Runnable{ 2 3 private int num = 100; 4 5 public void run() { 6 while(true) { 7 8 try { 9 Thread.sleep(10); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 show(); 14 15 } 16 } 17 18 public synchronized void show() { 19 20 if(num>0) 21 System.out.println(Thread.currentThread().getName()+" ticket="+num--); 22 } 23 }
在函数上加上修饰符synchronized,使得函数变成同步函数。与同步代码块不同的是:同步代码块可以使用任意的对象作为锁,而同步函数只能使用本类的this作为锁。
当同步函数是静态的时候,此时要保证两种同步都要使用一个锁,就可以用this.getClass()、类.class作为锁
死锁:
1 package javase; 2 3 class LockObject{ 4 public static final Object obj1 = new Object(); 5 public static final Object obj2 = new Object(); 6 } 7 8 class DeadLock implements Runnable{ 9 10 private boolean falg; 11 public DeadLock(boolean falg) { 12 this.falg = falg; 13 } 14 15 @Override 16 public void run() { 17 18 if(falg) { 19 while(true) 20 synchronized (LockObject.obj1) { 21 System.out.println("if---obj1"); 22 synchronized (LockObject.obj2) { 23 System.out.println("if---obj2"); 24 } 25 } 26 27 } 28 else { 29 while(true) 30 synchronized (LockObject.obj2) { 31 System.out.println("else---obj2"); 32 synchronized (LockObject.obj1) { 33 System.out.println("else---obj1"); 34 } 35 } 36 } 37 38 } 39 40 } 41 42 public class DeadLockTest { 43 44 public static void main(String[] args) { 45 46 DeadLock d1 = new DeadLock(true); 47 DeadLock d2 = new DeadLock(false); 48 49 Thread t1 = new Thread(d1); 50 Thread t2 = new Thread(d2); 51 52 t1.start(); 53 t2.start(); 54 55 } 56 57 }
死锁是因为两个以上的锁在互相调用,线程a进入后并没有释放当前它所使用的锁1。此时另线程b获得执行权进入,他拿到了自己的锁2后,准备进入锁1时发现锁1还在被线程a使用,而线程a发现锁2也被线程b使用了。造成互相拿着锁使得别人和自己也无法进入的现象