synchronized关键字的详细分析和代码实例

  在Java中,通常都是经过同步机制来解决线程安全问题的,在JDK 5.0以后又新增了Lock的方式来实现线程安全。因此说实现线程安全方式一共有三种方法java

方式一:安全

synchronized(同步监视器){多线程

  //须要被同步的代码(操做共享数据的代码就是须要被同步的代码)ide

}this

经过继承Thread类的方式实现多线程并解决线程安全问题:spa

 1 package com.baozi.java;
 2 
 3 public class WinowTest {
 4     public static void main(String[] args){
 5         Window w1=new Window();
 6         Window w2=new Window();
 7         Window w3=new Window();
 8         w1.start();
 9         w2.start();
10         w3.start();
11     }
12 }
13 //经过继承Thread类的方法来实现多线程
14 class Window extends Thread {
15     private static int ticket = 100;
16     @Override
17     public void run() {
18         while (true) {
19             //这里经过synchronized代码块的形式来实现线程安全
20             synchronized (Window.class) {
21                 if (ticket > 0) {
22                     try {
23                         Thread.sleep(100);
24                     } catch (InterruptedException e) {
25                         e.printStackTrace();
26                     }
27                     System.out.println(Thread.currentThread().getName() + ":" + ticket--);
28                 } else {
29                     break;
30                 }
31             }
32         }
33 
34     }
35 }

经过实现Runnable接口的方式实现多线程并解决线程安全问题:线程

 1 package com.baozi.java;
 2 
 3 public class WindowTest2 {
 4     public static void main(String[] args){
 5         Window2 window2 = new Window2();
 6         Thread t1 = new Thread(window2);
 7         Thread t2 = new Thread(window2);
 8         t1.setName("线程1");
 9         t2.setName("线程2");
10         t1.start();
11         t2.start();
12     }
13 
14 }
15 //经过实现Runnable接口的方式实现多线程
16 class Window2 implements Runnable{
17     private  int ticket = 100;
18     @Override
19     public void run() {
20         while (true) {
21             //这里经过synchronized代码块的形式来实现线程安全
22             synchronized (this) {
23                 if (ticket > 0) {
24                     try {
25                         Thread.sleep(100);
26                     } catch (InterruptedException e) {
27                         e.printStackTrace();
28                     }
29                     System.out.println(Thread.currentThread().getName() + ":" + ticket--);
30                 } else {
31                     break;
32                 }
33             }
34         }
35 
36     }
37 }

备注:code

  同步监视器:其实就是咱们平时说的锁,任何一个类对象均可以充当同步监视器,而且针对须要操做的共享数据,要求多个线程必须共享同一个同步监视器,这样才能实现多线程共享数据的线程安全。对象

  同步方法解决了线程安全问题,可是在操做同步代码块的时候,实质上某一时刻只有一个线程拥有锁,其余线程须要操做共享数据的时候只能等待该线程释放了所以后经过抢占方式得到锁以后才能执行。言外之意针对共享数据实际上是单线程执行,这样会形成效率很是低。blog

方式二:

若是多个线程操做的共享数据的代码完整的声明在一个方法中,那么咱们使用synchronized关键字修饰这个方法为同步方法。

经过继承Thread类的方式实现多线程并解决线程安全问题:

 1 package com.baozi.java;
 2 
 3 public class WindowTest3 {
 4     public static void main(String[] args) {
 5         Window3 w1 = new Window3();
 6         Window3 w2 = new Window3();
 7         Window3 w3 = new Window3();
 8         w1.start();
 9         w2.start();
10         w3.start();
11     }
12 }
13 
14 //经过继承Thread类的方法来实现多线程
15 class Window3 extends Thread {
16     private static int ticket = 100;
17 
18     @Override
19     public void run() {
20         while (true) {
21             show();
22         }
23     }
24 
25     //这里经过synchronized方法的形式来实现线程安全
26     public static synchronized void show() {
27         if (ticket > 0) {
28             try {
29                 Thread.sleep(100);
30             } catch (InterruptedException e) {
31                 e.printStackTrace();
32             }
33             System.out.println(Thread.currentThread().getName() + ":" + ticket--);
34         }
35     }
36 }

经过实现Runnable接口的方式实现多线程并解决线程安全问题:

 

 1 package com.baozi.java;
 2 
 3 public class WindowTest2 {
 4     public static void main(String[] args) {
 5         Window2 window2 = new Window2();
 6         Thread t1 = new Thread(window2);
 7         Thread t2 = new Thread(window2);
 8         t1.setName("线程1");
 9         t2.setName("线程2");
10         t1.start();
11         t2.start();
12     }
13 }
14 //经过实现Runnable接口的方式实现多线程
15 class Window2 implements Runnable {
16     private int ticket = 100;
17 
18     @Override
19     public synchronized void run() {
20         while (true) {
21             if (ticket > 0) {
22                 try {
23                     Thread.sleep(100);
24                 } catch (InterruptedException e) {
25                     e.printStackTrace();
26                 }
27                 System.out.println(Thread.currentThread().getName() + ":" + ticket--);
28             } else {
29                 break;
30             }
31         }
32     }
33 }

 

备注:同步方法依然会涉及到同步监视器,只是不须要我么显示的声明。

  非静态的同步方法:同步监视器能够是this(当前对象)

  静态的同步方法:同步监视器能够是当前类

这样咱们就能省去单独造一个对象来充当同步监视器,使代码比较简单整洁。

方式三:

使用Lock锁的方式实现线程安全,这是JDK5.0新增长的方法,在后边单独分析。

相关文章
相关标签/搜索