synchronized可以鎖對象,代碼塊,類對象 ,那麼他們用起來會有區別嗎,這裏我們用實際代碼來探究下
package com.example.hxk.thread.synchroized;
public class SyncTest1 {
// synchronized修飾非靜態方法
public synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// synchronized代碼塊
public void test2() {
synchronized (this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();
new Thread(new Runnable() {
@Override
public void run() {
t1.test1();
}
}, "thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}
運行結果:
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
這裏thread2會等thread1運行完成纔會開始運行,說明thread1和thread2請求的是同一把鎖,也就說明了 synchronized代碼塊鎖當前對象和鎖非靜態方法,他們的效果是一樣的, 鎖的都是當前對象。
然後我們再來看看類鎖,修改代碼如下
package com.example.hxk.thread.synchroized;
public class SyncTest1 {
// 修飾靜態方法
public static synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 修飾類對象
public void test2() {
synchronized (SyncTest1.class) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();
new Thread(new Runnable() {
@Override
public void run() {
SyncTest1.test1();
}
}, "thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}
運行結果:
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
這裏可以看到thread2也是被thread1阻塞,所以他們持有的是同一把鎖,也就說明synchronized修飾靜態方法和鎖類對象,他們的效果是一樣的。 接下來我們同時用類鎖和對象鎖試試,代碼如下
package com.example.hxk.thread.synchroized;
public class SyncTest1 {
// 修飾靜態方法
public static synchronized void test1() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 修飾類對象
public synchronized void test2() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SyncTest1 t1 = new SyncTest1();
new Thread(new Runnable() {
@Override
public void run() {
SyncTest1.test1();
}
}, "thread1").start();
new Thread(new Runnable() {
@Override
public void run() {
t1.test2();
}
}, "thread2").start();
}
}
運行結果:
thread1 : 0
thread2 : 0
thread1 : 1
thread2 : 1
thread2 : 2
thread1 : 2
thread2 : 3
thread1 : 3
thread2 : 4
thread1 : 4
運行結果是交替進行的,說明對象鎖和類鎖鎖的不是同一個鎖,他們是兩個鎖,互不影響
總結:
1,synchronized修飾在非靜態方法上和synchronized(this){} 同步代碼塊效果是一樣的
2,synchronized修飾在靜態方法上和 synchronized (SyncTest1.class) {} 同步代碼塊效果是一樣的
3,synchronized修飾在非靜態方法表示鎖的是當前對象,修飾靜態方法表示鎖的是類對象(一個類在jvm中只有一個class對象)