一、同步(synchronized)和異步(asynchronized)
1、同步(synchronized)簡單說可以理解為共享的意思,如果資源不是共享的,就沒必要進行同步。設置共享資源為同步的話,可以避免一些臟讀情況。
2、異步(asynchronized)簡單說可以理解為獨立不受到其他任何制約。
舉個例子:
線程1調用了帶有synchronized關鍵字的方法methodA,線程2調用了異步方法methodB,出現的現象是同時控制臺輸出 t1,t2。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package com.ietree.multithread.sync; /** * 多線程之對象同步鎖和異步鎖Demo * * @author ietree */ public class SynAndAsynDemo { public static void main(String[] args) { final SynAndAsynDemo mo = new SynAndAsynDemo(); Thread t1 = new Thread( new Runnable() { @Override public void run() { mo.methodA(); } }, "t1" ); Thread t2 = new Thread( new Runnable() { @Override public void run() { mo.methodB(); } }, "t2" ); t1.start(); t2.start(); } // 方法A public synchronized void methodA(){ try { System.out.println(Thread.currentThread().getName()); // 休眠4秒 Thread.sleep( 4000 ); } catch (InterruptedException e) { e.printStackTrace(); } } // 方法B public void methodB(){ System.out.println(Thread.currentThread().getName()); } } |
線程1調用了帶有synchronized關鍵字的方法methodA,線程2調用了帶有synchronized關鍵字的方法methodB,出現的現象是首先輸出t1,等待4秒之后再輸出t2。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package com.ietree.multithread.sync; /** * 多線程之對象同步鎖和異步鎖Demo * * @author ietree */ public class SynAndAsynDemo { public static void main(String[] args) { final SynAndAsynDemo mo = new SynAndAsynDemo(); Thread t1 = new Thread( new Runnable() { @Override public void run() { mo.methodA(); } }, "t1" ); Thread t2 = new Thread( new Runnable() { @Override public void run() { mo.methodB(); } }, "t2" ); t1.start(); t2.start(); } // 方法A public synchronized void methodA(){ try { System.out.println(Thread.currentThread().getName()); // 休眠4秒 Thread.sleep( 4000 ); } catch (InterruptedException e) { e.printStackTrace(); } } // 方法B public synchronized void methodB(){ System.out.println(Thread.currentThread().getName()); } } |
結論:
在第一段代碼中t1線程先持有object對象的Lock鎖,t2線程可以以異步的方式調用對象中的非synchronized修飾的方法,所以同時輸出;
在第二段代碼中t1線程先持有object對象的Lock鎖,t2線程如果在這個時候調用對象中的同步(synchronized)方法則需等待,也就是同步。
二、volatile
作用:volatile關鍵字的作用是:使變量在多個線程間可見(具有可見性),但是僅靠volatile是不能保證線程的安全性,volatile關鍵字不具備synchronized關鍵字的原子性。
Demo1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.ietree.multithread.sync; public class RunThread extends Thread { // volatile private boolean isRunning = true ; private void setRunning( boolean isRunning) { this .isRunning = isRunning; } public void run() { System.out.println( "進入run方法.." ); int i = 0 ; while (isRunning == true ) { // .. } System.out.println( "線程停止" ); } public static void main(String[] args) throws InterruptedException { RunThread rt = new RunThread(); rt.start(); Thread.sleep( 1000 ); rt.setRunning( false ); System.out.println( "isRunning的值已經被設置了false" ); } } |
程序輸出:
1
2
3
4
|
進入run方法.. isRunning的值已經被設置了 false 之后進入死循環 |
Demo2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
package com.ietree.multithread.sync; public class RunThread extends Thread { // volatile private volatile boolean isRunning = true ; private void setRunning( boolean isRunning) { this .isRunning = isRunning; } public void run() { System.out.println( "進入run方法.." ); int i = 0 ; while (isRunning == true ) { // .. } System.out.println( "線程停止" ); } public static void main(String[] args) throws InterruptedException { RunThread rt = new RunThread(); rt.start(); Thread.sleep( 1000 ); rt.setRunning( false ); System.out.println( "isRunning的值已經被設置了false" ); } } |
程序輸出:
1
2
|
isRunning的值已經被設置了 false 線程停止 |
總結:當多個線程之間需要根據某個條件確定 哪個線程可以執行時,要確保這個條件在 線程之間是可見的。因此,可以用volatile修飾。
volatile 與 synchronized 的比較:
①volatile輕量級,只能修飾變量。synchronized重量級,還可修飾方法
②volatile只能保證數據的可見性,不能用來同步,因為多個線程并發訪問volatile修飾的變量不會阻塞。
synchronized不僅保證可見性,而且還保證原子性,因為,只有獲得了鎖的線程才能進入臨界區,從而保證臨界區中的所有語句都全部執行。多個線程爭搶synchronized鎖對象時,會出現阻塞。
線程安全性包括兩個方面,①可見性。②原子性。
從上面自增的例子中可以看出:僅僅使用volatile并不能保證線程安全性。而synchronized則可實現線程的安全性。
以上這篇詳談Java多線程的幾個常用關鍵字就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。