溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java基礎(chǔ)之synchronized

發(fā)布時(shí)間:2020-09-28 20:23:55 來源:網(wǎng)絡(luò) 閱讀:171 作者:專注地一哥 欄目:編程語言

synchronized
synchronized是一個(gè)同步鎖關(guān)鍵字,作用就是讓線程只能逐一執(zhí)行,不能并行執(zhí)行,至于底層怎么實(shí)現(xiàn),不是我這種連用都不會(huì)的人改關(guān)注的。
用法
– 修飾代碼快(非靜態(tài))
測(cè)試代碼(不加synchronized):
public class Synchronized {
public static void main (String[] args) {
Teacher teacher = new Teacher();
Thread first = new SynchronizedThread("first", teacher);
Thread second = new SynchronizedThread("second", teacher);
first.start();
second.start();
}
static class SynchronizedThread extends Thread {
private String name;
private Teacher teacher;
public SynchronizedThread (String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;}
@Override
br/>}
@Override
teacher.say(name);
}
}
static class Teacher {
public void say(String name) {
System.out.println("我正在教" + name);
//System.out.println("線程進(jìn)入睡眠");
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
}
}
執(zhí)行結(jié)果:
我正在教first
我正在教second
second睡眠三秒
first睡眠三秒
兩個(gè)睡眠三秒幾乎是同時(shí)出現(xiàn)。
測(cè)試代碼(加synchronized):
static class Teacher {
public void say(String name) {
System.out.println("我正在教" + name);
synchronized (this) {
//System.out.println("線程進(jìn)入睡眠");
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
}
}
輸出結(jié)果:
我正在教first
我正在教second
first睡眠三秒
second睡眠三秒
雖然看著是一樣的,實(shí)際輸出的時(shí)候,是先輸出一個(gè)睡眠三秒,3秒之后,再輸出一個(gè)睡眠三秒。
總結(jié):在多個(gè)線程操作同一個(gè)對(duì)象,執(zhí)行加鎖的對(duì)象方法的時(shí)候,逐一執(zhí)行同步代碼塊中的代碼,鎖的是對(duì)象實(shí)例
– 修飾對(duì)象方法
測(cè)試代碼(加synchronized):
static class Teacher {
public synchronized void say(String name) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
}
執(zhí)行結(jié)果:
我正在教first
first睡眠三秒
我正在教second
second睡眠三秒
可以看到輸出結(jié)果是先是一個(gè)線程(first)執(zhí)行了方法,然后是另外一個(gè)線程(second)執(zhí)行了方法。
測(cè)試代碼(不加synchronized):
static class Teacher {
public void say(String name) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
}
執(zhí)行結(jié)果:
我正在教first
我正在教second
second睡眠三秒
first睡眠三秒
可以看到兩個(gè)線程幾乎同時(shí)執(zhí)行了,這和代碼塊的測(cè)試是一樣的結(jié)果。
測(cè)試代碼(一個(gè)方法不加synchronized,一個(gè)方法加synchronized):
public class Synchronized {
public static void main (String[] args) {
Teacher teacher = new Teacher();
Thread first = new SynchronizedThread("first", teacher);
Thread second = new AnotherSynchronizedThread("second", teacher);
first.start();
second.start();
}
static class SynchronizedThread extends Thread {
private String name;
private Teacher teacher;
public SynchronizedThread (String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;}
@Override
br/>}
@Override
teacher.say(name);
}
}
static class AnotherSynchronizedThread extends Thread {
private String name;
private Teacher teacher;
public AnotherSynchronizedThread (String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;}
@Override
br/>}
@Override
teacher.hello(name);
}
}
static class Teacher {
public synchronized void say(String name) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
public void hello(String name) {
System.out.println("我會(huì)說hello");
System.out.println("hello " + name);
}
}
}
執(zhí)行結(jié)果:
我正在教first
我會(huì)說hello
hello second
first睡眠三秒
可以看到,多線線程執(zhí)行同一個(gè)對(duì)象的同步方法和非同步方法的時(shí)候,兩個(gè)方法的執(zhí)行相互不影響。
測(cè)試代碼(一個(gè)方法加synchronized,另外一個(gè)方法也加synchronized):
static class Teacher {
public synchronized void say(String name) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
public synchronized void hello(String name) {
System.out.println("我會(huì)說hello");
System.out.println("hello " + name);
}
}
執(zhí)行結(jié)果:
我正在教first
first睡眠三秒
我會(huì)說hello
hello second
雖然結(jié)果不能明顯看出輸出順序,但是執(zhí)行時(shí)我能看到是先執(zhí)行一個(gè)方法,執(zhí)行完之后再執(zhí)行另外一個(gè)方法。
測(cè)試代碼(一個(gè)靜態(tài)方法不加synchronized,一個(gè)對(duì)象方法加synchronized):
public class Synchronized {
public static void main (String[] args) {
Teacher teacher = new Teacher();
Thread first = new SynchronizedThread("first", teacher);
Thread second = new AnotherSynchronizedThread("second", teacher);
first.start();
second.start();
}
static class SynchronizedThread extends Thread {
private String name;
private Teacher teacher;
public SynchronizedThread (String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;}
@Override
br/>}
@Override
teacher.say(name);
}
}
static class AnotherSynchronizedThread extends Thread {
private String name;
private Teacher teacher;
public AnotherSynchronizedThread (String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;}
@Override
br/>}
@Override
Teacher.hello(name);
}
}
static class Teacher {
public synchronized void say(String name) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
public static void hello(String name) {
System.out.println("我會(huì)說hello");
System.out.println("hello " + name);
}
}
}
執(zhí)行結(jié)果:
我正在教first
我會(huì)說hello
hello second
first睡眠三秒
從結(jié)果上可以看到,對(duì)象方法上加同步對(duì)靜態(tài)方法沒有影響。
另外靜態(tài)方法加上了synchronized,兩個(gè)方法的執(zhí)行之間也不影響。
總結(jié):1、首先靜態(tài)方法加不加同步,對(duì)實(shí)例方法沒什么影響;
2、加同步的實(shí)例方法,對(duì)不加同步的實(shí)例方法沒什么影響;
3、只有都是實(shí)例方法并且都加同步的情況下,才會(huì)出現(xiàn)同步逐一執(zhí)行的效果;
靜態(tài)方法
– 靜態(tài)方法
上面已經(jīng)知道了對(duì)象方法加同步,對(duì)靜態(tài)方法沒有影響。
測(cè)試代碼(兩個(gè)靜態(tài)方法加synchronized):
static class Teacher {
public static synchronized void say(String name) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
public static synchronized void hello(String name) {
System.out.println("我會(huì)說hello");
System.out.println("hello " + name);
}
}
執(zhí)行結(jié)果:
我正在教first
first睡眠三秒
我會(huì)說hello
hello second
可以看到,是先執(zhí)行了一個(gè)方法,再執(zhí)行另外一個(gè)方法。
測(cè)試代碼(一個(gè)靜態(tài)方法加synchronized,一個(gè)靜態(tài)方法不加synchronized):
static class Teacher {
public static synchronized void say(String name) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
public static void hello(String name) {
System.out.println("我會(huì)說hello");
System.out.println("hello " + name);
}
}
執(zhí)行結(jié)果:
我正在教first
我會(huì)說hello
hello second
first睡眠三秒
兩個(gè)方法的執(zhí)行沒有影響。
總結(jié):靜態(tài)方法方法加同步只對(duì)加了XM代理申請(qǐng)www.fx61.com/brokerlist/xm.html同步的靜態(tài)方法有影響。
以上都是常規(guī)的寫法,實(shí)例方法給對(duì)象實(shí)例枷鎖,靜態(tài)方法給類枷鎖。還有一些其它的寫法。
其它寫法
測(cè)試代碼(在實(shí)例方法上加synchronized,加鎖的是類):
static class Teacher {
public static void say(String name) {
synchronized(Teacher.class) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
}
public static synchronized void hello(String name) {
System.out.println("我會(huì)說hello");
System.out.println("hello " + name);
}
}
執(zhí)行結(jié)果:
我正在教first
first睡眠三秒
我會(huì)說hello
hello second
執(zhí)行效果,類似與兩個(gè)加了同步的靜態(tài)方法,這種寫法是給類加鎖,所有需要同步類的方法都會(huì)受影響。
測(cè)試代碼(定義一個(gè)類變量(是一個(gè)對(duì)象),用來同步):
public class Synchronized {
private static Test lock = new Test();
public static void main (String[] args) {
Teacher teacher = new Teacher();
Thread first = new SynchronizedThread("first", teacher);
Thread second = new AnotherSynchronizedThread("second", teacher);
first.start();
second.start();
}
static class SynchronizedThread extends Thread {
private String name;
private Teacher teacher;
public SynchronizedThread (String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;}
@Override
br/>}
@Override
teacher.say(name);
}
}
static class AnotherSynchronizedThread extends Thread {
private String name;
private Teacher teacher;
public AnotherSynchronizedThread (String name, Teacher teacher) {
this.name = name;
this.teacher = teacher;}
@Override
br/>}
@Override
Teacher.hello(name);
}
}
static class Teacher {
public void say(String name) {
synchronized(lock) {
System.out.println("我正在教" + name);
SleepUtil.sleep(3000);
System.out.println(name + "睡眠三秒");
}
}
public static void hello(String name) {
synchronized(lock) {
System.out.println("我會(huì)說hello");
System.out.println("hello " + name);
}
}
}
static class Test {
}
}
執(zhí)行結(jié)果:
我正在教first
first睡眠三秒
我會(huì)說hello
hello second
這種寫法等效于類加同步,或者實(shí)例加同步,不過同步的對(duì)象變?yōu)榱俗约憾x的另外一個(gè)對(duì)象。
synchronized同步:
同步實(shí)例對(duì)象時(shí),只對(duì)使用這個(gè)對(duì)象鎖的方法有影響;
同步類時(shí),只對(duì)使用這個(gè)類鎖的方法有影響;

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI