日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java多线程--synchronized修饰普通方法和修饰静态方法的区别

發(fā)布時間:2025/1/21 java 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java多线程--synchronized修饰普通方法和修饰静态方法的区别 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

初始化一個對象時,會自動生成一個與該對象對應(yīng)的對象鎖,被synchronized 修飾的方法就得依靠對象鎖工作。當(dāng)多線程同時訪問某個被synchronized修飾的方法時,一旦某個進(jìn)程搶得對象鎖之后,其他的進(jìn)程只有排隊(duì)對待。

一、synchronized修飾普通方法

初始化一個對象時,會自動生成一個與該對象對應(yīng)的對象鎖,被synchronized 修飾的方法就得依靠對象鎖工作。當(dāng)多線程同時訪問某個被synchronized修飾的方法時,一旦某個進(jìn)程搶得對象鎖之后,其他的進(jìn)程只有排隊(duì)對待。

例如,Person類里有2個被synchronized 修飾的方法,…還是看代碼吧:

public class Person {public synchronized void eatApple() {Log.d("TAG", "eatApple begin at:" + System.currentTimeMillis());SystemClock.sleep(3000);Log.d("TAG", "eatApple end at:" + System.currentTimeMillis());}public synchronized void eatOrange() {for (int i = 0; i < 10; i++) {Log.d("TAG", "eatOrange is running");SystemClock.sleep(200);}} } public class MainActivity extends AppCompatActivity {Person person = new Person();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);thread1.start();thread2.start();}Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {person.eatApple();}});Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {person.eatOrange();}});}

運(yùn)行結(jié)果:

12-14 16:26:48.243 14867-14920/com.example.shengqf.myapplication D/TAG: eatApple begin at:1513240008242 12-14 16:26:51.244 14867-14920/com.example.shengqf.myapplication D/TAG: eatApple end at:1513240011243 12-14 16:26:51.246 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:51.447 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:51.648 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:51.848 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:52.049 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:52.250 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:52.451 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:52.652 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:52.853 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:26:53.055 14867-14921/com.example.shengqf.myapplication D/TAG: eatOrange is running

結(jié)論:因?yàn)閠hread1中的eatApple()方法和thread2中的eatOrange()方法都是通過person對象調(diào)用的,他們用的是同一個對象鎖,互斥。所以,thread2一直等到thread1中的eatApple()方法執(zhí)行完釋放了對象鎖后才開始執(zhí)行其eatOrange()方法。

現(xiàn)在將上面thread2代碼改一下:

Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {Person person2 = new Person();person2.eatOrange();}});

再運(yùn)行,結(jié)果:

12-14 16:43:05.011 16294-16320/com.example.shengqf.myapplication D/TAG: eatApple begin at:1513240985011 12-14 16:43:05.011 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:05.211 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:05.412 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:05.612 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:05.813 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:06.014 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:06.215 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:06.416 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:06.617 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:06.818 16294-16321/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-14 16:43:08.012 16294-16320/com.example.shengqf.myapplication D/TAG: eatApple end at:1513240988011

因?yàn)閠hread1中的eatApple()方法是通過person對象調(diào)用的,而thread2中的eatOrange()方法是通過person2對象調(diào)用的,他們用的是兩個不同的對象鎖,并不互斥。所以,thread2中的eatOrange()方法是和thread1中的eatApple()方法同時進(jìn)行的。

結(jié)論:使用“同一個對象”去調(diào)用其被synchronized 修飾的普通方法才互斥。

上面的Person類等效于:

public class Person{public void eatApple() {synchronized(Person.this){Log.d("TAG", "eatApple begin at:" + System.currentTimeMillis());SystemClock.sleep(3000);Log.d("TAG", "eatApple end at:" + System.currentTimeMillis());}}public void eatOrange() {synchronized (Person.this) {for (int i = 0; i < 10; i++) {Log.d("TAG", "eatOrange is running");SystemClock.sleep(200);}}} }
二、synchronized修飾靜態(tài)方法

直接看代碼:

public class Person {public synchronized static void eatApple() {Log.d("TAG", "eatApple begin at:" + System.currentTimeMillis());SystemClock.sleep(3000);Log.d("TAG", "eatApple end at:" + System.currentTimeMillis());}public synchronized static void eatOrange() {for (int i = 0; i < 10; i++) {Log.d("TAG", "eatOrange is running");SystemClock.sleep(200);}} } public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);thread1.start();thread2.start();}Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {Person.eatApple();}});Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {Person.eatOrange();}});}

運(yùn)行結(jié)果:

12-15 09:09:24.378 31625-31912/com.example.shengqf.myapplication D/TAG: eatApple begin at:1513300164378 12-15 09:09:27.379 31625-31912/com.example.shengqf.myapplication D/TAG: eatApple end at:1513300167379 12-15 09:09:27.381 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:27.582 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:27.783 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:27.984 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:28.184 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:28.385 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:28.585 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:28.786 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:28.986 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:09:29.188 31625-31913/com.example.shengqf.myapplication D/TAG: eatOrange is running

現(xiàn)在將thread1和thread2代碼改為:

Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {Person person1 = new Person();person1.eatApple();}});Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {Person person2 = new Person();person2.eatOrange();}});

再運(yùn)行結(jié)果:

12-15 09:12:38.316 32353-32378/com.example.shengqf.myapplication D/TAG: eatApple begin at:1513300358316 12-15 09:12:41.317 32353-32378/com.example.shengqf.myapplication D/TAG: eatApple end at:1513300361317 12-15 09:12:41.320 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:41.521 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:41.721 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:41.922 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:42.123 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:42.324 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:42.525 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:42.727 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:42.928 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running 12-15 09:12:43.129 32353-32379/com.example.shengqf.myapplication D/TAG: eatOrange is running

因?yàn)閑atApple()和eatOrange()方法都是Person類里的靜態(tài)方法,且被synchronized修飾,所以這兩個方法都是靠唯一的Person類鎖工作,所以無論是通過Person類名調(diào)用還是new不同的person對象調(diào)用,兩個方法都是互斥的。

結(jié)論:被synchronized 修飾的靜態(tài)方法要靠類鎖工作。當(dāng)多線程同時訪問某個被synchronized修飾的靜態(tài)方法時,一旦某個進(jìn)程搶得該類的類鎖之后,其他的進(jìn)程只有排隊(duì)對待。

上面的Person代碼等效于:

public class Person {public static void eatApple() {synchronized(Person.class){Log.d("TAG", "eatApple begin at:" + System.currentTimeMillis());SystemClock.sleep(3000);Log.d("TAG", "eatApple end at:" + System.currentTimeMillis());}}public static void eatOrange() {synchronized(Person.class){for (int i = 0; i < 10; i++) {Log.d("TAG", "eatOrange is running");SystemClock.sleep(200);}}} }

總結(jié)

以上是生活随笔為你收集整理的Java多线程--synchronized修饰普通方法和修饰静态方法的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。