Java語(yǔ)言的關(guān)鍵字,當(dāng)它用來(lái)修飾一個(gè)方法或者一個(gè)代碼塊的時(shí)候,能夠保證在同一時(shí)刻最多只有一個(gè)線程執(zhí)行該段代碼。
成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比順昌網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式順昌網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋順昌地區(qū)。費(fèi)用合理售后完善,十多年實(shí)體公司更值得信賴。
一、當(dāng)兩個(gè)并發(fā)線程訪問(wèn)同一個(gè)對(duì)象object中的這個(gè)synchronized(this)同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。
二、然而,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),另一個(gè)線程仍然可以訪問(wèn)該object中的非synchronized(this)同步代碼塊。
三、尤其關(guān)鍵的是,當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),其他線程對(duì)object中所有其它synchronized(this)同步代碼塊的訪問(wèn)將被阻塞。
四、第三個(gè)例子同樣適用其它同步代碼塊。也就是說(shuō),當(dāng)一個(gè)線程訪問(wèn)object的一個(gè)synchronized(this)同步代碼塊時(shí),它就獲得了這個(gè)object的對(duì)象鎖。結(jié)果,其它線程對(duì)該object對(duì)象所有同步代碼部分的訪問(wèn)都被暫時(shí)阻塞。
五、以上規(guī)則對(duì)其它對(duì)象鎖同樣適用.
線程同步主要有以下種方法(示例中是實(shí)現(xiàn)計(jì)數(shù)的功能):
1、同步方法,即使用synchronized關(guān)鍵字修飾方法,例如:
public?synchronized?void?add(int?c){...}
2、同步代碼塊,即有synchronized關(guān)鍵字修飾的語(yǔ)句塊,例如:
public?void?addAndGet(int?c){
synchronized(this){
count?+=?c;
}
}
3、使用特殊域變量(volatile)實(shí)現(xiàn)線程同步,該方法不能保證絕對(duì)的同步。
例如:private?volatile?int?count?=?0;
4、使用鎖實(shí)現(xiàn)線程同步,例如:
private?Lock?lock?=?new?ReentrantLock();
public?void?add(int?c)?{??
lock.lock();//上鎖??
try{??
count?+=?c;??
}finally{??
lock.unlock();//解鎖??
}??
}
5、使用原子變量實(shí)現(xiàn)線程同步,在java的util.concurrent.atomic包中提供了創(chuàng)建了原子類型變量的工具類,例如:
private?AtomicInteger?count=?new?AtomicInteger(1);
public?void?add(int?c)?{
count.addAndGet(c);
}
6、使用局部變量實(shí)現(xiàn)線程同步,如果使用ThreadLocal管理變量,則每一個(gè)使用該變量的線程都獲得該變量的副本, 副本之間相互獨(dú)立,這樣每一個(gè)線程都可以隨意修改自己的變量副本,而不會(huì)對(duì)其他線程產(chǎn)生影響。
ThreadLocal 類的常用方法
new ThreadLocalT() : 創(chuàng)建一個(gè)線程本地變量
get() : 返回此線程局部變量的當(dāng)前線程副本中的值
initialValue() : 返回此線程局部變量的當(dāng)前線程的"初始值"
set(T value) : 將此線程局部變量的當(dāng)前線程副本中的值設(shè)置為value
示例代碼:
private?static?ThreadLocalInteger?count=?new?ThreadLocalInteger(){
@Override
protected?Integer?initialValue(){?
return?1;
}
};????????????
public?void?add(int?c){
count.set(count.get()?+?c);
}
7、使用阻塞隊(duì)列實(shí)現(xiàn),例如LinkedBlockingQueue,具體使用可百度LinkedBlockingQueue的用法或查看java文檔。
synchronized同步代碼塊,用于進(jìn)行多線程同步使用,你所指的申明的對(duì)象,其實(shí)是線程鎖,當(dāng)一個(gè)線程執(zhí)行到synchronized時(shí),鎖就被鎖定,其他線程進(jìn)不來(lái),只能在外面等待,之所以不把鎖對(duì)象省略是因?yàn)椴煌男枨笮枰煌逆i,必須兩個(gè)線程用的是同一個(gè)類的兩個(gè)實(shí)例對(duì)象呢,每一個(gè)對(duì)象的this是不同的兩個(gè)對(duì)象,這個(gè)時(shí)候就鎖不住了,所以這個(gè)時(shí)候應(yīng)該用a.class
class a{
public void run{
synchronized (a.class){
System.out.println("xxxxx");
}
}