1.1 synchronized修飾的普通方法---------被同一個對象實例訪問
package com.ljf.mianshi.demo.mainshithread;
public class TestJd {
public static void main(String args[]){
JDSB jdsb=new JDSB();
JDSB jdsb2=new JDSB();
new Thread(new ThreadA(jdsb),"A").start();
new Thread(new ThreadB(jdsb),"B").start();
}
}
package com.ljf.mianshi.demo.mainshithread;
public class JDSB {
public synchronized void sayA() {
System.out.println("我是線程:"+Thread.currentThread().getName()+"我開始執行sayA");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是線程:"+Thread.currentThread().getName()+"我離開sayA");
}
}
package com.ljf.mianshi.demo.mainshithread;
public class ThreadA implements Runnable {
JDSB jdsb=null;
public ThreadA(JDSB jdsb) {
this.jdsb=jdsb;
}
@Override
public void run() {
jdsb.sayA();
}
}
package com.ljf.mianshi.demo.mainshithread;
public class ThreadB implements Runnable {
JDSB jdsb=null;
public ThreadB(JDSB jdsb) {
this.jdsb=jdsb;
}
@Override
public void run() {
jdsb.sayA();
}
}
結果:
我是線程:A我開始執行sayA
我是線程:A我離開sayA
我是線程:B我開始執行sayA
我是線程:B我離開sayA
結論:synchronized修飾普通方法,使用同一對象訪問,那麼結果是同步的。
1.2 synchronized修飾的普通方法---------被不同對象實例訪問
package com.ljf.mianshi.demo.mainshithread;
public class TestJd {
public static void main(String args[]){
JDSB jdsb=new JDSB();
JDSB jdsb2=new JDSB();
new Thread(new ThreadA(jdsb),"A").start();
new Thread(new ThreadB(jdsb2),"B").start();
}
}
package com.ljf.mianshi.demo.mainshithread;
public class JDSB {
public synchronized void sayA() {
System.out.println("我是線程:"+Thread.currentThread().getName()+"我開始執行sayA");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是線程:"+Thread.currentThread().getName()+"我離開sayA");
}
}
package com.ljf.mianshi.demo.mainshithread;
public class ThreadA implements Runnable {
JDSB jdsb=null;
public ThreadA(JDSB jdsb) {
this.jdsb=jdsb;
}
@Override
public void run() {
jdsb.sayA();
}
}
package com.ljf.mianshi.demo.mainshithread;
public class ThreadB implements Runnable {
JDSB jdsb=null;
public ThreadB(JDSB jdsb) {
this.jdsb=jdsb;
}
@Override
public void run() {
jdsb.sayA();
}
}
結果:
我是線程:B我開始執行sayA
我是線程:A我開始執行sayA
我是線程:B我離開sayA
我是線程:A我離開sayA
結論:synchronized修飾普通方法,使用不同對象訪問,那麼結果是異步的。不同的對象使用各自的鎖。
比較1.1和1.2得出的結論爲:synchronized修飾不加static的普通方法時使用的鎖是this對象,使用同一對象訪問,那麼結果是同步的,使用的是同一把鎖,使用不同對象訪問,那麼結果是異步的。不同的對象使用各自的鎖,不同的對象沒有競爭關係;
1.3 synchronized修飾static的方法---------被同一對象實例訪問
package com.ljf.mianshi.demo.mainshithread;
public class TestJd {
public static void main(String args[]){
JDSB jdsb=new JDSB();
JDSB jdsb2=new JDSB();
/** synchronized關鍵字加到static靜態方法上是給Class類(class字節碼文件)上鎖,
* 而Class鎖可以對類的所有對象實例起作用
*/
new Thread(new ThreadA(jdsb),"A").start();
new Thread(new ThreadB(jdsb),"B").start();
}
}
package com.ljf.mianshi.demo.mainshithread;
public class JDSB {
public static synchronized void sayA() {
System.out.println("我是線程:"+Thread.currentThread().getName()+"我開始執行sayA");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是線程:"+Thread.currentThread().getName()+"我離開sayA");
}
}
package com.ljf.mianshi.demo.mainshithread;
public class ThreadA implements Runnable {
JDSB jdsb=null;
public ThreadA(JDSB jdsb) {
this.jdsb=jdsb;
}
@Override
public void run() {
jdsb.sayA();
}
}
package com.ljf.mianshi.demo.mainshithread;
public class ThreadB implements Runnable {
JDSB jdsb=null;
public ThreadB(JDSB jdsb) {
this.jdsb=jdsb;
}
@Override
public void run() {
jdsb.sayA();
}
}
結果:
我是線程:A我開始執行sayA
我是線程:A我離開sayA
我是線程:B我開始執行sayA
我是線程:B我離開sayA
1.4 synchronized修飾static的方法---------被不同對象實例訪問
package com.ljf.mianshi.demo.mainshithread;
public class TestJd {
public static void main(String args[]){
JDSB jdsb=new JDSB();
JDSB jdsb2=new JDSB();
/** synchronized關鍵字加到static靜態方法上是給Class類(class字節碼文件)上鎖,
* 而Class鎖可以對類的所有對象實例起作用
*/
new Thread(new ThreadA(jdsb),"A").start();
new Thread(new ThreadB(jdsb2),"B").start();
}
}
package com.ljf.mianshi.demo.mainshithread;
public class JDSB {
public static synchronized void sayA() {
System.out.println("我是線程:"+Thread.currentThread().getName()+"我開始執行sayA");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是線程:"+Thread.currentThread().getName()+"我離開sayA");
}
}
package com.ljf.mianshi.demo.mainshithread;
public class ThreadA implements Runnable {
JDSB jdsb=null;
public ThreadA(JDSB jdsb) {
this.jdsb=jdsb;
}
@Override
public void run() {
jdsb.sayA();
}
}
package com.ljf.mianshi.demo.mainshithread;
public class ThreadB implements Runnable {
JDSB jdsb=null;
public ThreadB(JDSB jdsb) {
this.jdsb=jdsb;
}
@Override
public void run() {
jdsb.sayA();
}
}
經過1.3和1.4比較可得:而兩個對象是同一個class文件,所以使用的是一個鎖。
synchronized關鍵字加到static靜態方法上是給Class類(class字節碼文件)上鎖,而Class鎖可以對類的所有對象實例起作用,類鎖就是要控制類的所有實例的併發訪問,這個類所有的對象競爭一把鎖。
參考地址: