在Java編程中,多線程是非常常見(jiàn)的,而線程間共享變量的情況也經(jīng)常會(huì)遇到。在這種情況下,就需要考慮到數(shù)據(jù)的同步。Java提供了兩種方式來(lái)保證線程安全:volatile和synchronized。
volatile關(guān)鍵字
volatile關(guān)鍵字用于保證變量的可見(jiàn)性。當(dāng)一個(gè)變量被聲明為volatile時(shí),如果一個(gè)線程修改了這個(gè)變量的值,那么其他線程會(huì)立即看到這個(gè)變量的修改。volatile關(guān)鍵字的作用是禁止指令重排序,保證了代碼的執(zhí)行順序。
public class TestVolatile { private volatile boolean flag = false; public void setFlag(boolean flag) { this.flag = flag; } public void run() { while(!flag) { // do something } // do something when flag is true } }
上述代碼中,flag變量被聲明為volatile。如果在另一個(gè)線程中調(diào)用setFlag(true)方法,那么在當(dāng)前線程中的flag變量會(huì)立即被更新,從而讓當(dāng)前線程退出while循環(huán)。
synchronized關(guān)鍵字
synchronized關(guān)鍵字用于保證同一個(gè)時(shí)刻只能有一個(gè)線程訪問(wèn)某個(gè)對(duì)象或變量。它包括兩種使用方式:同步方法和同步塊。
1. 同步方法:
public class TestSync { private synchronized void synMethod() { // do something } }
在上述代碼中,synMethod方法被聲明為synchronized。當(dāng)線程訪問(wèn)該方法時(shí),會(huì)獲取該對(duì)象的鎖,其他線程需要等待該線程釋放該對(duì)象的鎖才能訪問(wèn)該方法。
2. 同步塊:
public class TestSync { private Object lock = new Object(); public void synBlock() { synchronized(lock) { // do something } } }
在上述代碼中,synBlock方法中使用了同步塊,在同步塊中使用了lock對(duì)象來(lái)同步。該方法中的同步塊只有獲取了lock對(duì)象的鎖才能訪問(wèn),在訪問(wèn)完同步塊后,會(huì)釋放lock對(duì)象的鎖。
總的來(lái)說(shuō),volatile關(guān)鍵字用于保證變量的可見(jiàn)性,而synchronized關(guān)鍵字用于保證同一個(gè)時(shí)刻只能有一個(gè)線程訪問(wèn)某個(gè)對(duì)象或變量,從而保證線程安全。