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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

相关疑惑解决,java线程虚假唤醒等等问题

發布時間:2024/10/5 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 相关疑惑解决,java线程虚假唤醒等等问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. System.out.println方法是線程安全的

之前一直疑惑為啥下面案例中的主線程中num = 1會對線程A可見,注意沒有加volatile修飾

class Test1{//public volatile static int num =0;public static int num =0;public static void main(String[] args) {new Thread(()->{while (num==0){System.out.println(Thread.currentThread().getName());}},"線程A").start();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}num = 1;System.out.println(num);} }

后來百度一下知道原來println()方法是線程安全的

//println方法的實現public void println(int x) {synchronized (this) {print(x);newLine();}}

JMM關于Synchronized的兩條規定:

線程加鎖時,講清空工作內存中共享變量的值,從而使用共享變量是需要從主內存中重新讀取最新的值(加鎖與解鎖需要統一把鎖)
線程解鎖前,必須把共享變量的最新值刷新到主內存中;

2. 虛假喚醒

public class PcModel {public static void main(String[] args){SynResource synResource = new SynResource();new Thread(()->{try {for (int i = 0; i < 10; i++) {synResource.increment();}} catch (InterruptedException e) {e.printStackTrace();}},"生產者").start();new Thread(()->{try {for (int i = 0; i < 10; i++) {synResource.increment();}} catch (InterruptedException e) {e.printStackTrace();}},"生產者副本").start();new Thread(()->{try {for (int i = 0; i < 10; i++) {synResource.decrement();}} catch (InterruptedException e) {e.printStackTrace();}},"消費者").start();new Thread(()->{try {for (int i = 0; i < 10; i++) {synResource.decrement();}} catch (InterruptedException e) {e.printStackTrace();}},"消費者副本").start();} }class SynResource{volatile private int count =0;synchronized void increment() throws InterruptedException {if (count == 1){this.wait();}System.out.println(Thread.currentThread().getName() + "+ 1");count++;this.notifyAll();}synchronized void decrement() throws InterruptedException {if (count == 0){this.wait();}System.out.println(Thread.currentThread().getName() + "- 1");count--;this.notifyAll();} }

上面是一個經典的生產者-消費者模型。當只有一個生產者和一個消費者時程序能正常運行,但如果按照上面的例子來運行??梢园l現運行結果并不是我們所想要的結果。這是因為if語句執行完后會接著向下執行,即當線程被喚醒重新獲得鎖后會接著向下運行,這時就會產生虛假喚醒的問題了(生產者和生產者副本都運行至this.wait()),如果把if語句改成while就能避免此中現象產生。

3. ReadWriteLock

  • 如果當前是寫鎖被占有了,只有當寫鎖的數據降為0時才認為釋放成功;否則失敗。因為只要有寫鎖,那么除了占有寫鎖的那個線程,其他線程即不可以獲得讀鎖,也不能獲得寫鎖
  • 如果當前是讀鎖被占有了,那么只有在寫鎖的個數為0時才認為釋放成功。因為一旦有寫鎖,別的任何線程都不應該再獲得讀鎖了,除了獲得寫鎖的那個線程。

4. static synchronized 修飾的方法中

當前鎖對象是 類.calss對象 注意與非靜態方法的區別

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的相关疑惑解决,java线程虚假唤醒等等问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。