我之前寫過一篇synchronized的文章,在那篇文章中安寺,我說
解決方法在函數(shù)上加鎖挑庶。
試過
public synchronized void function{
//代碼塊
}
試過
public void function{
synchronized(this){
//代碼塊
}
}
結果都是兩個線程同時執(zhí)行代碼塊挠羔。
正確方法:
class A
{
public void function{
synchronized(A.class)
{
//代碼塊
}
}
}
額埋嵌,發(fā)現(xiàn)synchronized(A.class)解決了我的問題范舀,就說它是對的锭环,別的是不對辅辩,真是大錯特錯蛾茉。今天研讀了synchronized的相關文章,來詳細寫下記錄撩鹿。
我自https://blog.csdn.net/luoweifu/article/details/46613015大牛處學習谦炬。
先從代碼上記錄synchronized的使用方式。
第一種
synchronized(this){
//代碼塊
}
第二種
synchronized(class) {
//代碼塊
}
第三種
public synchronized void function() {
//代碼塊
}
第四種
public synchronized static void function() {
//代碼塊
}
這四種的使用場景以及作用下面開始介紹节沦。
一和三作用的對象是調(diào)用這個代碼塊的對象键思。
二和四作用的對象是這個類的所有的對象。
代碼舉例說明:
一甫贯、第一種測試類對四種synchronized用法的結果吼鳞。
package test;
public class ThreadTest {
public static void main(String args[]) {
ThreadSync syncThread = new ThreadSync();
Thread thread1 = new Thread(syncThread, "SyncThread1");
Thread thread2 = new Thread(syncThread, "SyncThread2");
thread1.start();
thread2.start();
}
}
//因為只new了一個對象,所以對四種情況的結果預測是都線程同步
1获搏、第一種 synchronized(this){//代碼塊}
package test;
public class ThreadSync implements Runnable{
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
SyncThread2:0
SyncThread2:1
SyncThread2:2
SyncThread2:3
SyncThread2:4
結果:同步鎖赖条,線程同步。
2、第二種 synchronized(class){//代碼塊}
package test;
public class ThreadSync implements Runnable{
public void run() {
synchronized(ThreadSync.class) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
SyncThread2:0
SyncThread2:1
SyncThread2:2
SyncThread2:3
SyncThread2:4
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
結果:同步鎖墓贿,線程同步。
3、第三種 public synchronized void function() {//代碼塊}
package test;
public class ThreadSync implements Runnable{
public synchronized void run() {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
SyncThread2:0
SyncThread2:1
SyncThread2:2
SyncThread2:3
SyncThread2:4
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
結果:同步鎖击吱,線程同步。
4柴罐、第四種 public synchronized static void function() {//代碼塊}
package test;
public class ThreadSync implements Runnable{
public void run() {
function();
}
public synchronized static void function() {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
SyncThread2:0
SyncThread2:1
SyncThread2:2
SyncThread2:3
SyncThread2:4
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
結果:同步鎖那婉,線程同步呛谜。
結論:如果是單個對象訪問被修飾的方法或者代碼塊割坠,都可以實現(xiàn)同步鎖湘今。
二、第二種測試類對四種synchronized用法的結果。
package test;
public class ThreadTest {
public static void main(String args[]) {
ThreadSync syncThread1 = new ThreadSync();
ThreadSync syncThread2 = new ThreadSync();
Thread thread1 = new Thread(syncThread1, "SyncThread1");
Thread thread2 = new Thread(syncThread2, "SyncThread2");
thread1.start();
thread2.start();
}
}
//因為只new了兩個對象冻押,所以對四種情況的結果預測是第一種和第三種不同步,第二種和第四種同步
1漓库、第一種 synchronized(this){//代碼塊}
package test;
public class ThreadSync implements Runnable{
public void run() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
SyncThread2:0
SyncThread1:0
SyncThread2:1
SyncThread1:1
SyncThread2:2
SyncThread1:2
SyncThread1:3
SyncThread2:3
SyncThread1:4
SyncThread2:4
結果:同步鎖不成功少态,線程不同步澳骤,各走各的颊艳。
2妒峦、第二種 synchronized(class){//代碼塊}
package test;
public class ThreadSync implements Runnable{
public void run() {
synchronized(ThreadSync.class) {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
SyncThread2:0
SyncThread2:1
SyncThread2:2
SyncThread2:3
SyncThread2:4
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
結果:同步鎖漾脂,線程同步坦冠。
3、第三種 public synchronized void function() {//代碼塊}
package test;
public class ThreadSync implements Runnable{
public synchronized void run() {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
SyncThread1:0
SyncThread2:0
SyncThread1:1
SyncThread2:1
SyncThread2:2
SyncThread1:2
SyncThread1:3
SyncThread2:3
SyncThread2:4
SyncThread1:4
結果:同步鎖不成功奥吩,線程不同步旅东,各走各的。
4鞋既、第四種 public synchronized static void function() {//代碼塊}
package test;
public class ThreadSync implements Runnable{
public void run() {
function();
}
public synchronized static void function() {
for (int i = 0; i < 5; i++) {
try {
System.out.println(Thread.currentThread().getName() + ":" + i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
SyncThread2:0
SyncThread2:1
SyncThread2:2
SyncThread2:3
SyncThread2:4
SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
結果:同步鎖陡舅,線程同步茎芋。
結論:如果是一個類的多個對象訪問被修飾的方法或者代碼塊涛酗,修飾靜態(tài)方法的方式和修飾類的方式可以實現(xiàn)同步鎖沈自,保證只有多個對象只有單個線程進入方法體酪夷。修飾普通方法的方式和修飾對象的方式只能鎖住單個對象。
這里從大牛的博客里摘抄一個知識點硫戈。
當有一個明確的對象作為鎖時锰什,就可以用類似下面這樣的方式寫程序。
public void method3(SomeObject obj)
{
//obj 鎖定的對象
synchronized(obj)
{
// todo
}
}
當沒有明確的對象作為鎖丁逝,只是想讓一段代碼同步時歇由,可以創(chuàng)建一個特殊的對象來充當鎖:
class Test implements Runnable
{
private byte[] lock = new byte[0]; // 特殊的instance變量
public void method()
{
synchronized(lock) {
// todo 同步代碼塊
}
}
public void run() {
}
}
---------------------
作者:luoweifu
來源:CSDN
原文:https://blog.csdn.net/luoweifu/article/details/46613015
版權聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接果港!
說明:零長度的byte數(shù)組對象創(chuàng)建起來將比任何對象都經(jīng)濟――查看編譯后的字節(jié)碼:生成零長度的byte[]對象只需3條操作碼,而Object lock = new Object()則需要7行操作碼糊昙。