例子一:一個對象,兩個加鎖方法
下面代碼運行結果是先輸出打電話還是發短信
public class Test1 {
public static void main(String[] args) {
Phone phone= new Phone();
//這裏的->是lambda表達式的寫法
new Thread(()-> {
phone.sendMessage();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
public synchronized void sendMessage(){
System.out.println("發短信");
}
public synchronized void call(){
System.out.println("打電話");
}
}
例子二:在例子一的基礎上讓第一個加鎖方法睡眠4秒再執行
下面代碼運行結果是先輸出打電話還是發短信
public class Test1 {
public static void main(String[] args) {
Phone phone= new Phone();
//這裏的->是lambda表達式的寫法
new Thread(()-> {
phone.sendMessage();
},"A").start();
//捕獲
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
//synchronized 鎖的對象是方法的調用者
//兩個方法調用的是同個鎖即Phone,說先獲取到就誰先輸出
public synchronized void sendMessage(){
try {
//睡眠4秒再執行
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
//synchronized 鎖的對象是方法的調用者
public synchronized void call(){
System.out.println("打電話");
}
}
例子三:一個普通方法hello和一個加鎖的方法
下面代碼運行結果是先輸出你好還是發短信
public class Test2 {
public static void main(String[] args) {
Phone2 phone= new Phone2();
//這裏的->是lambda表達式的寫法
new Thread(()-> {
phone.sendMessage();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.hello();
},"B").start();
}
}
class Phone2{
public synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
//這裏沒有鎖,不是同步方法,不受鎖的影響
public void hello(){
System.out.println("你好");
}
}
例子四:兩個對象,兩個加鎖方法
下面代碼運行結果是先輸出打電話還是發短信
//兩個對象,兩個同步方法,先打電話後發短信
public class Test2 {
public static void main(String[] args) {
//兩個對象
Phone2 phone1= new Phone2();
Phone2 phone2= new Phone2();
//這裏的->是lambda表達式的寫法
new Thread(()-> {
phone1.sendMessage();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone2{
public synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
public synchronized void call(){
System.out.println("打電話");
}
}
例子五:一個對象,兩個static加鎖方法
下面代碼運行結果是先輸出打電話還是發短信
public class Test3 {
public static void main(String[] args) {
Phone3 phone= new Phone3();
//這裏的->是lambda表達式的寫法
new Thread(()-> {
phone.sendMessage();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone3{
//static靜態方法
//類一加載就有了 鎖的class類
//所以此時鎖的是同一個鎖
public static synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
public static synchronized void call(){
System.out.println("打電話");
}
}
例子六:兩個對象,兩個static加鎖方法
下面代碼運行結果是先輸出打電話還是發短信
public class Test3 {
public static void main(String[] args) {
//兩個對象的class類模板只有一個,static鎖的是class
Phone3 phone1= new Phone3();
Phone3 phone2= new Phone3();
//這裏的->是lambda表達式的寫法
new Thread(()-> {
phone1.sendMessage();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone3{
//static靜態方法
//類一加載就有了 鎖的class類
//所以此時鎖的是同一個鎖
public static synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
public static synchronized void call(){
System.out.println("打電話");
}
}
例子七:一個對象,一個static加鎖方法,一個普通加鎖同步方法
下面代碼運行結果是先輸出打電話還是發短信
public class Test4 {
public static void main(String[] args) {
Phone4 phone= new Phone4();
//這裏的->是lambda表達式的寫法
new Thread(()-> {
phone.sendMessage();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone4{
//靜態同步方法,鎖的類模板
public static synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
//普通同步方法,鎖的調用方法
public synchronized void call(){
System.out.println("打電話");
}
}
例子八:兩個對象,一個static加鎖方法,一個普通加鎖同步方法
下面代碼運行結果是先輸出打電話還是發短信
public class Test4 {
public static void main(String[] args) {
Phone4 phone1= new Phone4();
Phone4 phone2= new Phone4();
//這裏的->是lambda表達式的寫法
new Thread(()-> {
phone1.sendMessage();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone4{
//靜態同步方法,鎖的類模板
public static synchronized void sendMessage(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("發短信");
}
//普通同步方法,鎖的調用方法
public synchronized void call(){
System.out.println("打電話");
}
}
例子一運行結果:發短信 打電話
例子二運行結果:等待4秒後輸出 發短信 打電話
例子三運行結果:先輸出你好 後輸出 發短信
例子四運行結果:先輸出打電話 再發短信
例子五運行結果:先發短信後打電話
例子六運行結果:先發短信後打電話
例子七運行結果:先打電話,後發短信
例子八運行結果:先打電話,後發短信
小結
static synchronized 鎖的是class
synchronized 鎖的是對象
誰先獲取到對象誰就先執行
聲明:本文爲學習狂神說java的juc併發編程所做的筆記,狂神說javajuc併發編程地址:https://www.bilibili.com/video/BV1B7411L7tE?p=11