安全執行緒就是要保證資料的高度一致性和準確性,但不是一定要加鎖才是執行緒安全性,只要代碼裡沒有變數互串,線程之間互不影響,就是安全執行緒的。
要瞭解安全執行緒,可以先看一下線程不安全是怎樣的一種現象。
public class TreadNoSafeDemo { public static void main(String[] args) { new ThreadNoSafeTest().start(); new ThreadNoSafeTest().start(); new ThreadNoSafeTest().start(); new ThreadNoSafeTest().start(); }}class ThreadNoSafeTest extends Thread{ private int num=5; @Override public void run() { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"................."+(--num)); }}
由運行結果可以看出:–num輸出的並不是我們認為的 4 3 2 1;這就是線程的不安全現象。
那怎麼才能實現安全執行緒呢。Java給我們提供了哪些機制。
想要實現安全執行緒大致有三種方法: 不適用單例模式,而是用多執行個體。 使用鎖機制Synchronized、lock方式。 使用java.util.concurrent下面的類庫。
下面對具體的方法進行介紹:
隱式鎖(線程同步synchronized)
線程同步synchronized有兩種方式,一種是放在同步方法上,一種是放在同步代碼塊裡。
同步方法:
public synchronized void methodTest(){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "................." + (--num)); }
同步代碼塊
public void methodTest(){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (object) { System.out.println(Thread.currentThread().getName() + "................." + (--num)); } }
顯示鎖Lock和ReentrantLock
加鎖和解鎖都是顯示的。
Lock介面(java.util.concurrent.locks.Lock)的主要方法為:
ReentrantLock是Lock的實作類別,是一個互斥的同步器。
在競爭條件下ReentrantLock的實現要比synchronized的實現更具有伸縮性,這意味著當許多線程都競爭相同鎖定時,使用ReentrantLock的輸送量通常要比synchronized好。
ReentrantLock是對方法塊加鎖使用頻率最高點。
使用方法:
class ReentrantLockTest{ private final ReentrantLock reentrantLock=new ReentrantLock(); public void methodTest(){ reentrantLock.lock(); try { //............................... }catch (Exception e){ } reentrantLock.unlock(); }}
顯示鎖ReadWriteLock和ReentrantReadWriteLock
ReadWriteLock也是一個介面,提供了readLock和writeLock兩種鎖的操作機制,一個用於唯讀操作,另一個用於寫入操作。只要沒有 writer,讀取鎖可以由多個 reader 線程同時保持。寫入鎖是獨佔的。讀寫鎖使用的情境是一個共用資源被大量的讀取操作而只有少量的寫操作。(讀讀不互斥,讀寫互斥,寫寫互斥;)。
ReentrantReadWriteLock和ReentrantLock區別:ReentrantReadWriteLock是對ReentrantLock的複雜擴充,ReentrantReadWriteLock可以實現一個方法中讀寫分離的鎖的機制,而ReentrantLock加鎖解鎖只是一種機制。
顯示鎖StampedLock
StampedLock可大幅度提高程式的讀取鎖的輸送量。在大量都是讀取、很少寫入的情況下,樂觀讀鎖可以極大的提高輸送量,也可以減少這種情況下寫的饑餓現象。
查看:synchronized、ReentrantLock、ReentrantReadWriteLock 和StampedLock 的對比