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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 线程可见性,Java多线程之内存可见性

發布時間:2025/3/15 java 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 线程可见性,Java多线程之内存可见性 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java內存模型( JMM ) :

1) 所有的變量都存儲在主內存中

2) 每個線程都有自己獨立的工作內存, 里面保存該線程使用到的變量的副本 ( 主內存中該變量的一份拷貝 )

JMM兩條規定:

1) 線程對共享變量的所有操作都必須在自己的工作內存中進行

2) 不同線程之間無法直接訪問其他線程工作內存中的共享變量, 線程間共享變量值的傳遞必須通過主內存

線程間共享變量可見性實現的原理:

線程A 對共享變量的修改想被線程B 及時看到, 必須要經過以下2個步驟:

1) 把線程A 工作內存中更新過的共享變量刷新到主內存中( store )

2) 將主內存中最新的共享變量的值共享到線程B 工作內存中( load )

Java 語言層面支持的可見性實現方式:

1) synchronized

2) volatile

JUC 包下的類也可以實現可見性

1) Atomic

2)?ReentrantLock

3) Semaphore

1. synchronized 實現可見性

JMM 關于 synchronized 的兩條規定:

1) 線程釋放鎖前, 必須把共享變量的最新值從該線程的工作內存刷新到主內存中

2) 線程持有鎖時, 將清空該線程工作內存中共享變量的值, 從主內存中讀取最新的值

synchronized 實現可見性的原因:

線程釋放鎖前對共享變量的修改在下次持有鎖時對其他線程可見

public?class?SynchronizedDemo?{

//?共享變量

private?int?result?=?0;

//?共享變量執行自增操作

public?synchronized?void?increase()?{

result++;

}

public?int?getResult()?{

return?result;

}

public?static?void?main(String[]?args)?throws?InterruptedException?{

final?SynchronizedDemo?demo?=?new?SynchronizedDemo();

//?設置啟動500個線程

int?count?=?500;

//?創建一個?JUC?包下的同步同步計數器,?設置計數次數為線程數500

final?CountDownLatch?cdl?=?new?CountDownLatch(count);

for?(int?i?=?0;?i?

new?Thread(new?Runnable()?{

@Override

public?void?run()?{

demo.increase();

cdl.countDown();

}

}).start();

}

cdl.await();

System.out.println(demo.getResult());

}

}

Console 輸出: 500

synchronized 不僅可以實現可見性, 還可以實現原子性

volatile 如何實現可見性:

通過加入內存屏障和禁止指令重排序

1) 對 volatile 變量執行寫操作時, 會在寫操作后加入一條 store 屏障指令

2) 對 volatile 變量執行讀操作時, 會在讀操作前加入一條 load?屏障指令

public?class?VolatileDemo?{

//?使用?volatile?修飾共享變量

private?volatile?int?result?=?0;

//?共享變量?result?執行自增操作,?無法保證原子性

public?void?increase()?{

result++;

}

public?int?getResult()?{

return?result;

}

public?static?void?main(String[]?args)?throws?InterruptedException?{

final?VolatileDemo?demo?=?new?VolatileDemo();

//?設置啟動500個線程

int?count?=?500;

//?創建一個?JUC?包下的同步同步計數器,?設置計數次數為線程數500

final?CountDownLatch?cdl?=?new?CountDownLatch(count);

for?(int?i?=?0;?i?

new?Thread(new?Runnable()?{

@Override

public?void?run()?{

demo.increase();

cdl.countDown();

}

}).start();

}

cdl.await();

System.out.println(demo.getResult());

}

}

Console 輸出: 498

volatile 關鍵字, 能保證 volatile 變量的可見性, 不能保證 volatile 變量操作的原子性( 如 ++/-- )

3. AtomicInteger 實現可見性

用 Atomic 類實現共享變量在線程中的原子性( 通過 CAS, 自旋 實現)

public?class?AtomicIntegerDemo?{

//?共享變量

private?AtomicInteger?result?=?new?AtomicInteger(0);

//?使用?Atomic?類的?incrementAndGet()?方法(?原子操作?),?實現自增

public?void?increase()?{

result.incrementAndGet();

}

public?int?getResult()?{

return?result.get();

}

public?static?void?main(String[]?args)?throws?InterruptedException?{

final?AtomicIntegerDemo?demo?=?new?AtomicIntegerDemo();

//?設置啟動500個線程

int?count?=?500;

//?創建一個JUC包下的同步同步計數器,?設置計數次數為線程數500

final?CountDownLatch?cdl?=?new?CountDownLatch(count);

for?(int?i?=?0;?i?

new?Thread(new?Runnable()?{

@Override

public?void?run()?{

demo.increase();

cdl.countDown();

}

}).start();

}

cdl.await();

System.out.println(demo.getResult());

}

}

Console 輸出: 500

4. JUC 包下的 Lock 實現可見性

用 ReentrantLock 實現共享變量在線程中的原子性

public?class?LockDemo?{

//?共享變量

private?int?result?=?0;

//?可重入鎖

private?Lock?lock?=?new?ReentrantLock();

//?使用鎖機制,?保證鎖內代碼的原子性

public?void?increase()?{

//?加鎖

lock.lock();

try?{

result++;

}?finally?{

//?釋放鎖

lock.unlock();

}

}

public?int?getResult()?{

return?result;

}

public?static?void?main(String[]?args)?throws?InterruptedException?{

final?LockDemo?demo?=?new?LockDemo();

//?設置啟動500個線程

int?count?=?500;

//?創建一個JUC包下的同步同步計數器,?設置計數次數為線程數500

final?CountDownLatch?cdl?=?new?CountDownLatch(count);

for?(int?i?=?0;?i?

new?Thread(new?Runnable()?{

@Override

public?void?run()?{

demo.increase();

cdl.countDown();

}

}).start();

}

cdl.await();

System.out.println(demo.getResult());

}

}

Console 輸出: 500

5. Semaphore 實現可見性

用信號量機制實現共享變量在線程中的原子性

public?class?SemaphoreDemo?{

//?共享變量

private?int?result?=?0;

//?初始化信號量為1,?一次只能有1個線程訪問共享變量,?相當于互斥鎖

private?Semaphore?semaphore?=?new?Semaphore(1);

//?使用信號量機制,?保證共享變量自增操作的原子性

public?void?increase()?{

try?{

//?獲取1個信號量

semaphore.acquire();

}?catch?(InterruptedException?e)?{

e.printStackTrace();

}

result++;

//?釋放1個信號量

semaphore.release();

}

public?int?getResult()?{

return?result;

}

public?static?void?main(String[]?args)?throws?InterruptedException?{

final?SemaphoreDemo?demo?=?new?SemaphoreDemo();

//?設置啟動500個線程

int?count?=?500;

//?創建一個JUC包下的同步同步計數器,?設置計數次數為線程數500

final?CountDownLatch?cdl?=?new?CountDownLatch(count);

for?(int?i?=?0;?i?

new?Thread(new?Runnable()?{

@Override

public?void?run()?{

demo.increase();

cdl.countDown();

}

}).start();

}

cdl.await();

System.out.println(demo.getResult());

}

}

Console 輸出: 500

總結:

synchronized 代碼塊具備 可見性和 可見性

volatile變量具備可見性, 不具備原子性

總結

以上是生活随笔為你收集整理的java 线程可见性,Java多线程之内存可见性的全部內容,希望文章能夠幫你解決所遇到的問題。

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