【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
生活随笔
收集整理的這篇文章主要介紹了
【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文地址:https://www.cnblogs.com/edenpans/p/6020113.html
?
參考文章:http://ifeve.com/java-concurrency-thread-directory/?
其中的競態,線程安全,內存模型,線程間的通信,java ThreadLocal類小節部分內容。
- 1.目錄略覽
- 2.競態條件與臨界區
- 3.線程安全與共享資源
? ? ? 線程控制逃逸判斷
? ? ? ? ? ?一個資源的創建,使用銷毀都在同一個線程內完成,且永遠不會脫離該線程的控制。
即使對象本身線程安全,但是該對象中包含的其他的資源,也許整體的應用不是線程安全的。 3.線程安全及不可變性 immutable 和 read only 的差別:當一個變量是只讀的時候,變量的值不可改變,但是可以在其他變量發生改變的時候發生改變。而不變 是不會改變的。- ? ? ?4.java 內存模型
?
每個java虛擬機的線程都擁有自己的線程棧,包括了這個線程調用的方法當前執行點的相關信息。一個線程只能訪問自己的線程棧。本地變量只對當前線程可見。?
對象是放在堆上。 每個線程都有自己的線程棧,如果是基本類型的變量,直接存放在線程棧中,如果是對象的引用,那么引用地址會放在線程棧中,而對象會在堆中,這樣有可能存在兩個線程同時引用相同的對象。 public class MyRunnable implements Runnable() {public void run() {methodOne();}public void methodOne() {int localVariable1 = 45;MySharedObject localVariable2 =MySharedObject.sharedInstance;//... do more with local variables.methodTwo();}public void methodTwo() {Integer localVariable1 = new Integer(99);//... do more with local variable.} }public class MySharedObject {//static variable pointing to instance of MySharedObjectpublic static final MySharedObject sharedInstance =new MySharedObject();//member variables pointing to two objects on the heappublic Integer object2 = new Integer(22);public Integer object4 = new Integer(44);public long member1 = 12345;public long member1 = 67890; }?
兩個線程啟動后,Object3就是?MySharedObject,而Object2,Object4 是?? ?MySharedObject中的 object2 和 Object4. 現代硬件內存架構?
Java內存模型和硬件內存架構之間的橋接?
硬件內存架構中沒有區分線程棧和堆。對于硬件所有線程棧和堆都是分布在主存中。部分線程棧和堆可能出現在CPU緩存和CPU內部的寄存器中。 當對象和變量被存放在計算機不同的內存區域中時,會有一些問題: 1.線程對共享變量修改的可見性。— 兩個線程分布運行在不同的CPU上時,線程的部分變量沒有刷新回主存,此時可能會導致不同步。可以使用 volatile 來避免。 2.當讀,寫和檢查共享變量時出現race conditions。多個線程同時修改共享內存的值,如下圖:?
可以使用java同步塊,這樣同一時刻只能有一個線程可以進入代碼的臨界區。同步塊還可以保證代碼塊中所有被訪問的變量從主存中讀入,當線程退出同步塊時,所有被更新的變量也會被刷新回主存中,無論該變量是否被聲明為volatile. 5.java 同步塊 java同步塊 (synchronized block) 用來標記方法或者代碼塊是同步的。用來避免競爭。 java同步關鍵字:synchronized 所有其他等待進入該同步塊的線程將被阻塞,直到執行該同步塊的線程退出。 ? ?? 四種不同的同步塊: 實例方法;靜態方法;實例方法中的同步塊;靜態方法中的同步塊。——都是方法上的同步塊。 ? ?? 實例方法同步: public synchronized void add(int value){this.count += value;} 每個實例其方法同步都是同步在不同的對象上。這樣每個實例方法同步都同步在不同的對象上,即該方法所屬的實例,只有一個線程可以在實例方法同步塊中運行。一個實例一個線程。 靜態方法同步: public static synchronized void add(int value){count += value; } 靜態方法同步是指同步在該方法上所在的類對象上的。java虛擬機中一個類只能對應一個類對象,所以同時只允許一個線程執行同一個類中的靜態同步方法。不管類中的哪個靜態同步方法被調用,一個類只能由一個線程同時執行。 ? ? ? ? ? 實例方法中同步塊: public void add(int value){synchronized(this){this.count += value; }}? ? ? ? ? 示例中使用的this 是代表的調用add方法的實例本身。在同步構造器中用括號括起來的對象叫做監視器對象。
靜態方法中同步塊: public class MyClass {public static synchronized void log1(String msg1, String msg2){log.writeln(msg1);log.writeln(msg2);}public static void log2(String msg1, String msg2){synchronized(MyClass.class){log.writeln(msg1);log.writeln(msg2); }}} 兩個方法不允許同時被線程訪問。 如果第二個同步塊不是同步在MyClass.class這個同步器上,這兩個方法可以同時被線程訪問。 java同步示例: public class Counter{long count = 0;public synchronized void add(long value){this.count += value;}}public class CounterThread extends Thread{protected Counter counter = null;public CounterThread(Counter counter){this.counter = counter;}public void run() {for(int i=0; i<10; i++){counter.add(i);}}}public class Example {public static void main(String[] args){Counter counter = new Counter();Thread threadA = new CounterThread(counter);Thread threadB = new CounterThread(counter);threadA.start();threadB.start(); }}?
由于兩個線程都是共用一個counter實例,所以add()被調用的時候是同步的,只有一個線程可以調用,另外一個需要等待。 public class Example {public static void main(String[] args){Counter counterA = new Counter();Counter counterB = new Counter();Thread threadA = new CounterThread(counterA);Thread threadB = new CounterThread(counterB);threadA.start();threadB.start(); }} 這個時候兩個線程就可以同時調用add()方法,因為它們分別在不同的實例中。- 6.線程通信
- 6 Java ThreadLocal
?
轉載于:https://www.cnblogs.com/cheng2015/p/8487651.html
總結
以上是生活随笔為你收集整理的【转】JAVA 并发性和多线程 -- 读感 (二 线程间通讯,共享内存的机制)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3-4 第三天 Generator生成器
- 下一篇: LandsDesign(Rhino)莫名