synchronized简介
生活随笔
收集整理的這篇文章主要介紹了
synchronized简介
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Java語言的關鍵字,可用來給對象和方法或者代碼塊加鎖,當它鎖定一個方法或者一個代碼塊的時候,同一時刻最多只有一個線程執行這個段代碼。當兩個并發線程訪問同一個對象object中的這個加鎖同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊。然而,當一個線程訪問object的一個加鎖代碼塊時,另一個線程仍然可以訪問該object中的非加鎖代碼塊。
? synchronized 方法
例如: public synchronized void synMethod(){
//方法體
} 2.對某一代碼塊使用,synchronized后跟括號,括號里是變量,這樣,一次只有一個線程進入該代碼塊.此時,線程獲得的是成員鎖.例如: public int synMethod(inta1){
synchronized(a1){
//一次只能有一個線程進入
}
}
3.synchronized后面括號里是一對象,此時,線程獲得的是對象鎖.例如: public class MyThread implements Runnable{
public static void main(Stringargs[]){
MyThreadmt=newMyThread();
Threadt1=newThread(mt,"t1");
Threadt2=newThread(mt,"t2");
Threadt3=newThread(mt,"t3");
Threadt4=newThread(mt,"t4");
Threadt5=newThread(mt,"t5");
Threadt6=newThread(mt,"t6");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
public void run(){
synchronized(this){
System.out.println(Thread.currentThread().getName());
}
}
}
對于3,如果線程進入,則得到當前對象鎖,那么別的線程在該類所有對象上的任何操作都不能進行.在對象級使用鎖通常是一種比較粗糙的方法。為什么要將整個對象都上鎖,而不允許其他線程短暫地使用對象中其他同步方法來訪問共享資源?如果一個對象擁有多個資源,就不需要只為了讓一個線程使用其中一部分資源,就將所有線程都鎖在外面。由于每個對象都有鎖,可以如下所示使用虛擬對象來上鎖: class FineGrainLock{
MyMemberClassx,y;
Objectxlock=newObject(),ylock=newObject();
publicvoidfoo(){
synchronized(xlock){
//accessxhere
}
//dosomethinghere-butdon'tusesharedresources
synchronized(ylock){
//accessyhere
}
}
public void bar(){
synchronized(this){
//accessbothxandyhere
}
//dosomethinghere-butdon'tusesharedresources
}
}
4.synchronized后面括號里是類,此時,線程獲得的是對象鎖.例如: classArrayWithLockOrder{
privatestaticlongnum_locks=0;
privatelonglock_order;
privateint[]arr;
publicArrayWithLockOrder(int[]a)
{
arr=a;
synchronized(ArrayWithLockOrder.class){//-----這里
num_locks++;//鎖數加1。
lock_order=num_locks;//為此對象實例設置唯一的lock_order。
}
}
publiclonglockOrder()
{
returnlock_order;
}
publicint[]array()
{
returnarr;
}
}
classSomeClassimplementsRunnable
{
publicintsumArrays(ArrayWithLockOrdera1,
ArrayWithLockOrdera2)
{
intvalue=0;
ArrayWithLockOrderfirst=a1;//保留數組引用的一個
ArrayWithLockOrderlast=a2;//本地副本。
intsize=a1.array().length;
if(size==a2.array().length)
{
if(a1.lockOrder()>a2.lockOrder())//確定并設置對象的鎖定
{//順序。
first=a2;
last=a1;
}
synchronized(first){//按正確的順序鎖定對象。
synchronized(last){
int[]arr1=a1.array();
int[]arr2=a2.array();
for(inti=0;i<size;i++)
value+=arr1[i]+arr2[i];
}
}
}
returnvalue;
}
publicvoidrun(){
//
}
}
對于4,如果線程進入,則線程在該類中所有操作不能進行,包括靜態變量和靜態方法,實際上,對于含有靜態方法和靜態變量的代碼塊的同步,我們通常用4來加鎖.
目錄
1概述
2對synchronized(this)的一些理解
3synchronized的4種用法
1概述編輯
synchronized 關鍵字,代表這個方法加鎖,相當于不管哪一個線程(例如線程A),運行到這個方法時,都要檢查有沒有其它線程B(或者C、 D等)正在用這個方法,有的話要等正在使用synchronized方法的線程B(或者C 、D)運行完這個方法后再運行此線程A,沒有的話,直接運行。它包括兩種用法:synchronized 方法和 synchronized 塊。synchronized 方法
1.方法聲明時使用,放在范圍操作符(public等)之后,返回類型聲明(void等)之前.這時,線程獲得的是成員鎖,即一次只能有一個線程進入該方法,其他線程要想在此時調用該方法,只能排隊等候,當前線程(就是在synchronized方法內部的線程)執行完該方法后,別的線程才能進入.例如: public synchronized void synMethod(){
//方法體
} 2.對某一代碼塊使用,synchronized后跟括號,括號里是變量,這樣,一次只有一個線程進入該代碼塊.此時,線程獲得的是成員鎖.例如: public int synMethod(inta1){
synchronized(a1){
//一次只能有一個線程進入
}
}
3.synchronized后面括號里是一對象,此時,線程獲得的是對象鎖.例如: public class MyThread implements Runnable{
public static void main(Stringargs[]){
MyThreadmt=newMyThread();
Threadt1=newThread(mt,"t1");
Threadt2=newThread(mt,"t2");
Threadt3=newThread(mt,"t3");
Threadt4=newThread(mt,"t4");
Threadt5=newThread(mt,"t5");
Threadt6=newThread(mt,"t6");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
public void run(){
synchronized(this){
System.out.println(Thread.currentThread().getName());
}
}
}
對于3,如果線程進入,則得到當前對象鎖,那么別的線程在該類所有對象上的任何操作都不能進行.在對象級使用鎖通常是一種比較粗糙的方法。為什么要將整個對象都上鎖,而不允許其他線程短暫地使用對象中其他同步方法來訪問共享資源?如果一個對象擁有多個資源,就不需要只為了讓一個線程使用其中一部分資源,就將所有線程都鎖在外面。由于每個對象都有鎖,可以如下所示使用虛擬對象來上鎖: class FineGrainLock{
MyMemberClassx,y;
Objectxlock=newObject(),ylock=newObject();
publicvoidfoo(){
synchronized(xlock){
//accessxhere
}
//dosomethinghere-butdon'tusesharedresources
synchronized(ylock){
//accessyhere
}
}
public void bar(){
synchronized(this){
//accessbothxandyhere
}
//dosomethinghere-butdon'tusesharedresources
}
}
4.synchronized后面括號里是類,此時,線程獲得的是對象鎖.例如: classArrayWithLockOrder{
privatestaticlongnum_locks=0;
privatelonglock_order;
privateint[]arr;
publicArrayWithLockOrder(int[]a)
{
arr=a;
synchronized(ArrayWithLockOrder.class){//-----這里
num_locks++;//鎖數加1。
lock_order=num_locks;//為此對象實例設置唯一的lock_order。
}
}
publiclonglockOrder()
{
returnlock_order;
}
publicint[]array()
{
returnarr;
}
}
classSomeClassimplementsRunnable
{
publicintsumArrays(ArrayWithLockOrdera1,
ArrayWithLockOrdera2)
{
intvalue=0;
ArrayWithLockOrderfirst=a1;//保留數組引用的一個
ArrayWithLockOrderlast=a2;//本地副本。
intsize=a1.array().length;
if(size==a2.array().length)
{
if(a1.lockOrder()>a2.lockOrder())//確定并設置對象的鎖定
{//順序。
first=a2;
last=a1;
}
synchronized(first){//按正確的順序鎖定對象。
synchronized(last){
int[]arr1=a1.array();
int[]arr2=a2.array();
for(inti=0;i<size;i++)
value+=arr1[i]+arr2[i];
}
}
}
returnvalue;
}
publicvoidrun(){
//
}
}
對于4,如果線程進入,則線程在該類中所有操作不能進行,包括靜態變量和靜態方法,實際上,對于含有靜態方法和靜態變量的代碼塊的同步,我們通常用4來加鎖.
2對synchronized(this)的一些理解編輯
一、當兩個并發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程得到執行。另一個線程必須等待當前線程執行完這個代碼塊以后才能執行該代碼塊。 二、然而,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。 三、尤其關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。 四、第三個例子同樣適用其它同步代碼塊,它就獲得了這個object的對象鎖。結果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞。 五、以上規則對其它對象鎖同樣適用。3synchronized的4種用法編輯
1.方法聲明時使用,放在范圍操作符(public等)后,其返回類型聲明(void等)之前。即一次只能有一個線程進入該方法,其他線程要想在此時調用該方法,只能排隊等候,當前線程(就是在synchronized方法內部的線程)執行完該方法后,別的線程才能進入。 例如: public synchronized void synMethod() { //方法體 } 2.對某一代碼塊使用,synchronized后跟括號,括號里是變量,這樣,一次只有一個線程進入該代碼塊。例如: public int synMethod(Object a1){ synchronized(Object) { //一次只能有一個線程進入 } } 3.synchronized后面括號里是一對象,此時,線程獲得的是對象鎖。例如: public class MyThread implements Runnable { public static void main(String args[]) { MyThread mt = new MyThread(); Thread t1 = new Thread(mt, "t1"); Thread t2 = new Thread(mt, "t2"); Thread t3 = new Thread(mt, "t3"); Thread t4 = new Thread(mt, "t4"); Thread t5 = new Thread(mt, "t5"); Thread t6 = new Thread(mt, "t6"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); t6.start(); } public void run() { synchronized (this) { System.out.println(Thread.currentThread().getName()); } } } 對于3,如果線程進入,則得到對象鎖,那么別的線程在該類所有對象上的任何操作都不能進行。在對象級使用鎖通常是一種比較粗糙的方法。為什么要將整個對象都上鎖,而不允許其他線程短暫地使用對象中其他同步方法來訪問共享資源?如果一個對象擁有多個資源,就不需要只為了讓一個線程使用其中一部分資源,就將所有線程都鎖在外面。由于每個對象都有鎖,可以如下所示使用虛擬對象來上鎖: class FineGrainLock { MyMemberClass x, y; Object xlock = new Object(), ylock = new Object(); public void foo() { synchronized(xlock) { //access x here } //do something here - but don‘t use shared resources synchronized(ylock) { //access y here } } public void bar() { synchronized(this) { //access both x and y here } //do something here - but don‘t use shared resources } } 4.synchronized后面括號里是類。例如: class ArrayWithLockOrder{ private static long num_locks = 0; private long lock_order; private int[] arr; public ArrayWithLockOrder(int[] a) { arr = a; synchronized(ArrayWithLockOrder.class) {//-----------------------------------------這里 num_locks++; // 鎖數加 1。 lock_order = num_locks; // 為此對象實例設置唯一的 lock_order。 } } public long lockOrder() { return lock_order; } public int[] array() { return arr; } } class SomeClass implements Runnable { public int sumArrays(ArrayWithLockOrder a1, ArrayWithLockOrder a2) { int value = 0; ArrayWithLockOrder first = a1; // 保留數組引用的一個 ArrayWithLockOrder last = a2; // 本地副本。 int size = a1.array().length; if (size == a2.array().length) { if (a1.lockOrder() > a2.lockOrder()) // 確定并設置對象的鎖定 { // 順序。 first = a2; last = a1; } synchronized(first) { // 按正確的順序鎖定對象。 synchronized(last) { int[] arr1 = a1.array(); int[] arr2 = a2.array(); for (int i=0;i<size;i++)value += arr1[i] + arr2[i]; } } } return value; } public void run() { //... } } 對于4,如果線程進入,則線程在該類中所有操作不能進行,包括靜態變量和靜態方法,實際上,對于含有靜態方法和靜態變量的代碼塊的同步,我們通常用4來加鎖。 以上4種之間的關系: 鎖是和對象相關聯的,每個對象有一把鎖,為了執行synchronized語句,線程必須能夠獲得synchronized語句中表達式指定的對象的鎖,一個對象只有一把鎖,被一個線程獲得之后它就不再擁有這把鎖,線程在執行完synchronized語句后,將獲得鎖交還給對象。 在方法前面加上synchronized修飾符即可以將一個方法聲明為同步化方法。同步化方法在執行之前獲得一個鎖。如果這是一個類方法,那么獲得的鎖是和聲明方法的類相關的Class類對象的鎖。如果這是一個實例方法,那么此鎖是this對象的鎖。synchronzied塊后面跟類的具體詳細例子: public class DB2_JDBCFactory { private static DB2_JDBCFactory instance = null; public static final ThreadLocal threadLocal = new ThreadLocal(); private DB2_JDBCFactory() { } public static DB2_JDBCFactory getInstance() { if(instance == null) { synchronized(DB2_JDBCFactory.class) { //synchronized后面跟一個類 instance = new DB2_JDBCFactory(); } } return instance; } public Connection getConnection_JNDI_localhost(){ Connection c = (Connection) threadLocal.get(); try { if (c == null || c.isClosed()) { InitialContext ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/localhost"); c = ds.getConnection(); threadLocal.set(c); } } catch (Exception ex) { System.err.println("getConnection_JNDI Initial failed. " + ex); return null; } return c; } } 外面的對象訪問這個類的 需要通過調用它的getInstance()總結
以上是生活随笔為你收集整理的synchronized简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: weblogic各个版本对JDK和Spr
- 下一篇: 编程神回复:在学习编程时,你觉得必须读的