java线程池 synchronized_java多线程学习(二) 之 synchronized
在實現線程同步方法里,synchronized是java中最簡單的方法。
官方解釋:
The use of synchronized methods or statements provides access to the implicit monitor lock associated with every object, but forces all lock acquisition and
release to occur in a block-structured way
synchronized 的使用有同步方法,和同步代碼塊,它提供了對一個對象隱式監視器鎖的訪問,也就是說synchronized之所以能實現線程間同步,是通過獲取對象的鎖實現的,只是這個鎖是隱式的,看不見的,默認java每個對象都有一個鎖存在。還有之所以說synchronized是java中實現線程同步最簡單的方法,是因為synchronized對鎖的獲取和釋放是有限制的,必須是在一個方法或者一段代碼塊前后。
synchronized 有兩種使用方法:
一種是修飾方法,修飾方法的時候,如果是修飾的普通方法,那就是獲取這個類對應的實例的鎖,如果是修飾的靜態方法,那就是獲取這個類的Class對象的鎖。例如:
public MyObject{
public synchronized void print()
{
//TODO
}
public static synchronized void printStatic()
{
//TODO
}
}
MyObject my = new MyObject();
也就是說,一個線程在執行my.print()之前必須先獲取my這個對象對應的隱式鎖,在方法執行完之后自動釋放。同樣的一個線程在執行MyObject.printStatic()之前必須線獲取MyObject.class這個對象的鎖。如果對象的鎖被別的線程占用,在調用方法的時候,線程就會等待在那里,直到別的線程釋放鎖為止。
另外一種方法是修飾代碼塊,表示在執行一塊代碼之前明確要求要獲取哪個對象的鎖,這種方法釋放鎖的標志是代碼塊執行結束,例如
public MyObject{
private MyLock mylock = new MyLock();
public void print1()
{
synchronized(this)
{
//todo;
}
}
public void print2()
{
synchronized(MyObject.class)
{
//todo;
}
}
public void print3()
{
synchronized(MyObject2.class)
{
//todo;
}
}
public void print4()
{
synchronized(mylock)
{
//todo;
}
}
}
代碼已經很明確了,你可以以任何對象作為鎖對象。需要說明的時,這里線程之間的同步,只是針對synchronized修飾過的代碼,而且必須是鎖對象是相同的,才會發生線程互斥,線程等待。對于沒有synchronized或者鎖對象不同的線程是不互斥的,是可以同步執行的。
例如第一種里的print方法和第二種里print1里的代碼塊都是鎖的相應的對象,一個線程如果執行對象my.print()的時候,另外一個線程在調my.print1()的時候,就會堵塞在synchronized(this)的地方,直到my.print()執行結束,釋放鎖。
還有我們說的線程互斥,是指兩個線程之間,如果是一個線程內部是可以重復獲取一個鎖的,自己不會和自己互斥的。也就是說synchronized可以嵌套:
public MyObject{
public void print1()
{
synchronized(this)
{
synchronized(this)
{
//todo;
}
}
}
}
當然,如果synchronized嵌套鎖不同的對象,那就有可能發生線程之間死鎖的問題,那就是另外一個話題了。
總結
以上是生活随笔為你收集整理的java线程池 synchronized_java多线程学习(二) 之 synchronized的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Python语音识别项目笔记] 3so
- 下一篇: 科大星云诗社动态20201130