【多執行緒】執行緒中的同步鎖synchronized
阿新 • • 發佈:2019-01-31
當多個執行緒同時執行時,由於cpu是隨機分片的,所以,一個執行緒在執行過程中被另一個執行緒打斷的情況是經常發生的。
這在某些情況下是會影響到正常的程式的輸出結果的。比如銀行轉賬一個人的賬戶在轉賬時是不能允許同時有另外一個執行緒也在執行的。
這就是執行緒同步要解決的問題。
通常發生在存在共享資料的時候。如果沒有共享資料,就不會出現加鎖的問題。
執行緒不同步問題引入
public class TestSync implements Runnable{
Timer timer=new Timer();//都是同一個物件
public static void main (String[] args){
TestSync test=new TestSync();
Thread t1=new Thread(test);
Thread t2=new Thread(test);
t1.setName("t1");
t2.setName("2");
t1.start();
t2.start();
}
public void run(){
timer.add(Thread.currentThread().getName());
}
}
class Timer{
private static int num=0;
public void add(String name){
num++;
try{
//這裡的sleep只是放大了效果,如果沒有sleep,這種被打斷也是存在的。
Thread.sleep(1);//1睡眠,2去執行
}catch(InterruptedException e){
return;
}
System.out.println(name+"你是第"+num+"個使用timer的執行緒");
}
}
執行上面的小程式,我們發現執行的結果是:
thread-0你是第2個使用timer的執行緒
thread-1你是第2個使用timer的執行緒
分析其原因:是在執行第一個執行緒的過程中,當執行到num++時,這個時候num=1,但是還沒打印出結果時,cpu就去執行第二個執行緒了,
這個時候又執行了num++這個時候num=2了,同時cpu又去執行第一個執行緒開始列印結果,然後再去列印第二個執行緒的結果,就出現上述這種情況了。
那麼,為了解決這種問題,我們就需要用執行緒同步的思想,讓執行緒1完全執行完以後,再去執行執行緒2。因為兩個執行緒之間存在共享變數。
所以不能允許兩個執行緒同時操作一個變數。
synchronized
其中一種解決上述問題的就是通過synchronized同步鎖來實現執行緒同步。
class Timer{
private static int num=0;
public synchronized void add(String name){
//synchronized(this){
num++;
try{
Thread.sleep(1);
}catch(InterruptedException e){
return;
}
System.out.println(name+"你是第"+num+"個使用timer的執行緒");
//}
}
}
可以實現同步塊的方式,也可以使用同步方法的方式。在這裡都是可以的。
synchronized個人理解:
同步鎖,就好像擁有一個房間的一把鎖一樣,只有你拿到這把鎖的鑰匙,那麼你才能進入這個房間。
同步鎖可分為很多級別的,類級別的,方法級別的和程式碼塊級別的。
其中方法級別和程式碼塊級別的加鎖都是針對訪問的物件內部加鎖的。如果一個物件的某一個方法加鎖了,
那麼這個物件還是可以訪問其他沒有加鎖的方法或者屬性的。而其他物件(新new出來的物件)仍然可以同時訪問當前這個加鎖的方法。
當然這樣的話,執行緒之間的物件就不是共享的了。
而類級別的鎖,是針對於同一個類不同的訪問物件。這樣只要一個例項物件擁有了這個類的鎖,那麼其他例項物件是不能擁有這個類的鎖的。
以上是我對synchronized這個同步鎖的理解。