1.什麼時候用原子操作類,舉個例子?
比如一個自增的操作就可以用原則操作類,原子操作類底層用的就是CAS。
2.什麼時候用volitile,舉個例子?
比如一個boolean的flag,因爲它與上個狀態無關。
3.手寫程序,10個多線程保證 i從0加到10?
可以用原子操作類來實現
import java.util.concurrent.atomic.AtomicInteger;
public class Autoincrease {
public static void main(String[] args)
{
atomicThread matomicThread=new atomicThread();
for(int i=0;i<10;i++)
{
Thread thread=new Thread(matomicThread);
thread.start();
}
}
public static class atomicThread implements Runnable
{
public AtomicInteger i=new AtomicInteger();
@Override
public void run() {
while(true)
{
try {
Thread.sleep(1000);
}catch (Exception e)
{
e.printStackTrace();
}
System.out.println("線程: " + Thread.currentThread().getName() + "將數據變爲: " + i.getAndIncrement());
}
}
}
}
4.如何避免死鎖?
主要有三種方式:
這篇文章對於死鎖的講解還是不錯的
(1)加鎖順序
當多個線程需要相同的一些鎖,但是按照不同的順序加鎖,死鎖就很容易發生。
比如線程一lockA lockB線程二lockB lockA那麼線程一佔有A管線程二要B,但此時線程二佔有B,它又去管線程一要A,這樣就造成了死鎖。如果要是都是一樣的順序的話,那麼就可以避免死鎖了。
按照順序加鎖是一種有效的死鎖預防機制。但是,這種方式需要你事先知道所有可能會用到的鎖(譯者注:並對這些鎖做適當的排序),但總有些時候是無法預知的。
(2)加鎖時限
超時自動釋放鎖,就算髮生死鎖了,也會自動解開。
這種機制存在一個問題,在Java中不能對synchronized同步塊設置超時時間。你需要創建一個自定義鎖,或使用Java5中java.util.concurrent包下的工具。寫一個自定義鎖類不復雜,
(3)死鎖檢測
死鎖檢測是一個更好的死鎖預防機制,它主要是針對那些不可能實現按序加鎖並且鎖超時也不可行的場景。
當發現死鎖的時候,一個可行的做法是釋放所有鎖,回退,並且等待一段隨機的時間後重試。一個更好的方案是給這些線程設置優先級,讓一個(或幾個)線程回退,剩下的線程就像沒發生死鎖一樣繼續保持着它們需要的鎖。
5.公平鎖與非公平鎖的區別?
tryAcquire是公平鎖和非公平鎖實現的區別,兩種類型的鎖都是tryAcquire實現的。每一次的tryAcquire都會檢查隊列中是否仍有前驅的元素,如果仍然有那麼繼續等待,通過這種方式來保證先來先服務的原則;而非公平鎖,首先是檢查並設置鎖的狀態,這種方式會出現即使隊列中有等待的線程,但是新的線程仍然會與排隊線程中的對頭線程競爭(但是排隊的線程是先來先服務的),所以新的線程可能會搶佔已經在排隊的線程的鎖,這樣就無法保證先來先服務,但是已經等待的線程們是仍然保證先來先服務的。
公平鎖能保證:老的線程排隊使用鎖,新線程仍然排隊使用鎖。
非公平鎖保證:老的線程排隊使用鎖;但是無法保證新線程搶佔已經在排隊的線程的鎖。
6.synchronized與Lock的區別?
synchronized是一個關鍵字,可重入,不可判斷鎖的狀態,非公平,自動釋放鎖。
Lock是一個類,可重入,可判斷鎖的狀態,可公平也可非公平(默認非公平,可構造的時候在ReentrantLock中加入true參數),必須主動釋放鎖。