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使用了。造成互相拿着锁使得别人和自己也无法进入的现象

原文地址:https://www.cnblogs.com/lsy-lsy/p/10907408.html