執行緒高階篇-Synchronized鎖,Lock鎖區別和Condition執行緒並行
淺談Synchronized:
synchronized是Java的一個關鍵字,也就是Java語言內建的特性,如果一個程式碼塊被synchronized修飾了,當一個執行緒獲取了對應的鎖,執行程式碼塊時,其他執行緒
便只能一直等待,等待獲取鎖的執行緒釋放鎖,而獲取鎖的執行緒釋放鎖會有三種情況:
1).獲取鎖的執行緒執行完該程式碼塊,然後執行緒釋放對鎖的佔有;
2).執行緒執行發生異常,此時JVM會讓執行緒自動釋放鎖;
3).呼叫wait方法,在等待的時候立即釋放鎖,方便其他的執行緒使用鎖.
Lock的特性:
1).Lock不是Java語言內建的;
2).synchronized是在JVM層面上實現的,如果程式碼執行出現異常,JVM會自動釋放鎖,但是Lock不行,要保證鎖一定會被釋放,就必須將unLock放到finally{}中(手動釋放);
3).在資源競爭不是很激烈的情況下,Synchronized的效能要優於ReetarntLock,但是在很激烈的情況下,synchronized的效能會下降幾十倍;
4).ReentrantLock增加了鎖:
a. void lock(); // 無條件的鎖;
b. void lockInterruptibly throws InterruptedException;//可中斷的鎖;
解釋: 使用ReentrantLock如果獲取了鎖立即返回,如果沒有獲取鎖,當前執行緒處於休眠狀態,直到獲得鎖或者當前執行緒可以被別的執行緒中斷去做其他的事情;但是如果是synchronized的話,如果沒有獲取到鎖,則會一直等待下去;
c. boolean tryLock();//如果獲取了鎖立即返回true,如果別的執行緒正持有,立即返回false,不會等待;
d. boolean tryLock(long timeout,TimeUnit unit);//如果獲取了鎖立即返回true,如果別的執行緒正持有鎖,會等待引數給的時間,在等待的過程中,如果獲取鎖,則返回true,如果等待超時,返回false;
5)Lock的ReentrantReadWriteLock讀寫鎖 適用於 讀多寫少的場景 效率較高
Condition的特性:
1.Condition中的await()方法相當於Object的wait()方法,Condition中的signal()方法相當於Object的notify()方法,Condition中的signalAll()相當於Object的notifyAll()方法。不同的是,Object中的這些方法是和同步鎖捆綁使用的;而Condition是需要與互斥鎖/共享鎖捆綁使用的。
2.Condition它更強大的地方在於:能夠更加精細的控制多執行緒的休眠與喚醒。對於同一個鎖,我們可以建立多個Condition,在不同的情況下使用不同的Condition。
例如,假如多執行緒讀/寫同一個緩衝區:當向緩衝區中寫入資料之後,喚醒”讀執行緒”;當從緩衝區讀出資料之後,喚醒”寫執行緒”;並且當緩衝區滿的時候,”寫執行緒”需要等待;當緩衝區為空時,”讀執行緒”需要等待。
如果採用Object類中的wait(), notify(), notifyAll()實現該緩衝區,當向緩衝區寫入資料之後需要喚醒”讀執行緒”時,不可能通過notify()或notifyAll()明確的指定喚醒”讀執行緒”,而只能通過notifyAll喚醒所有執行緒(但是notifyAll無法區分喚醒的執行緒是讀執行緒,還是寫執行緒)。 但是,通過Condition,就能明確的指定喚醒讀執行緒。
例項
ListAdd.java 使用synchronized
package ThreadCollections;
import java.util.ArrayList;
import java.util.List;
/**
* Created by 胖大星 on 2017/9/12.
*/
public class ListAdd {
private volatile static List list = new ArrayList();
public void addList(){
list.add("hello");
}
public int size(){
return list.size();
}
public static void main(String[] agrs){
final ListAdd list1 = new ListAdd();
Object lock = new Object();
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
try {
synchronized (lock){
for (int i = 0; i < 10; i++) {
list1.addList();
System.out.println("當前執行緒為: "+Thread.currentThread().getName()+" "+i);
Thread.sleep(500);
if(list.size() == 5){
System.out.println("當前通知已發出!");
lock.notify();
}
}
}
}
catch (InterruptedException e){
e.printStackTrace();
}
}
},"t1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
if (list1.size() != 5) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("當前執行緒:" + Thread.currentThread().getName()+"已經收到通知");
throw new RuntimeException();
}
}
},"t2");
thread2.start();
thread.start();
}
}
UseReentrantLock.java 使用Lock
package Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by 胖大星 on 2017/9/17.
* Lock 比 synchronized 方法更加便捷,靈活
*/
public class UseReentrantLock {
//new ReentrantLock(false) 可以帶引數 false 表示非公平鎖(根據cpu分配優先執行) true表示公平鎖(先來先執行)
private ReentrantLock lock = new ReentrantLock();
public void method1(){
try {
lock.lock();
System.out.println("當前執行緒:"+Thread.currentThread().getName()+"進入method1...");
Thread.sleep(1000);
System.out.println("當前執行緒:"+Thread.currentThread().getName()+"退出method1...");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void method2(){
try {
lock.lock();
System.out.println("當前執行緒:"+Thread.currentThread().getName()+"進入method2...");
Thread.sleep(1000);
System.out.println("當前執行緒:"+Thread.currentThread().getName()+"退出method2...");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public static void main(String[] args) {
UseReentrantLock useReentrantLock = new UseReentrantLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
useReentrantLock.method1();
useReentrantLock.method2();
}
}, "t1");
t1.start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
UseManyCondition.java 使用多個Condition
package Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by 胖大星 on 2017/9/17.
*啟動多個 Condition 並行鎖 同時並行多個執行緒
*/
public class UseManyCondition {
private ReentrantLock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
public void m1(){
try {
lock.lock();
System.out.println("當前執行緒:" +Thread.currentThread().getName() + "進入方法m1等待..");
c1.await();
System.out.println("當前執行緒:" +Thread.currentThread().getName() + "方法m1繼續..");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void m2(){
try {
lock.lock();
System.out.println("當前執行緒:" +Thread.currentThread().getName() + "進入方法m2等待..");
c1.await();
System.out.println("當前執行緒:" +Thread.currentThread().getName() + "方法m2繼續..");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void m3(){
try {
lock.lock();
System.out.println("當前執行緒:" +Thread.currentThread().getName() + "進入方法m3等待..");
c2.await();
System.out.println("當前執行緒:" +Thread.currentThread().getName() + "方法m3繼續..");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void m4(){
try {
lock.lock();
System.out.println("當前執行緒:" +Thread.currentThread().getName() + "喚醒..");
c1.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void m5(){
try {
lock.lock();
System.out.println("當前執行緒:" +Thread.currentThread().getName() + "喚醒..");
c2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
final UseManyCondition umc = new UseManyCondition();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
umc.m1();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
umc.m2();
}
},"t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
umc.m3();
}
},"t3");
Thread t4 = new Thread(new Runnable() {
@Override
public void run() {
umc.m4();
}
},"t4");
Thread t5 = new Thread(new Runnable() {
@Override
public void run() {
umc.m5();
}
},"t5");
t1.start(); // c1
t2.start(); // c1
t3.start(); // c2
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t4.start(); // c1
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t5.start(); // c2
}
}
UseReentrantReadWriteLock.java Lock使用讀寫鎖
package Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Created by 胖大星 on 2017/9/17.
* lock的ReentrantReadWriteLock讀寫鎖 適用於 讀多寫少的場景 效率較高
*/
public class UseReentrantReadWriteLock {
private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
private ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
private ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
public void read(){
try {
readLock.lock();
System.out.println("當前執行緒:"+Thread.currentThread().getName()+"進入....");
Thread.sleep(3000);
System.out.println("當前執行緒:"+Thread.currentThread().getName()+"退出....");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
readLock.unlock();
}
}
public void write(){
try {
writeLock.lock();
System.out.println("當前執行緒:"+Thread.currentThread().getName()+"進入....");
Thread.sleep(3000);
System.out.println("當前執行緒:"+Thread.currentThread().getName()+"退出....");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
writeLock.unlock();
}
}
public static void main(String[] args) {
UseReentrantReadWriteLock useReentrantReadWriteLock = new UseReentrantReadWriteLock();
Thread threadRead1 = new Thread(new Runnable() {
@Override
public void run() {
useReentrantReadWriteLock.read();
}
}, "threadRead1");
Thread threadRead2 = new Thread(new Runnable() {
@Override
public void run() {
useReentrantReadWriteLock.read();
}
}, "threadRead2");
Thread threadWrite1 = new Thread(new Runnable() {
@Override
public void run() {
useReentrantReadWriteLock.write();
}
}, "threafWrite1");
Thread threadWrite2 = new Thread(new Runnable() {
@Override
public void run() {
useReentrantReadWriteLock.write();
}
}, "threafWrite2");
//兩個讀執行緒同時開始 ,寫執行緒明顯較慢
threadRead1.start();
// threadRead2.start();
threadWrite1.start();
// threadWrite2.start();
}
}
相關推薦
執行緒高階篇-Synchronized鎖,Lock鎖區別和Condition執行緒並行
淺談Synchronized: synchronized是Java的一個關鍵字,也就是Java語言內建的特性,如果一個程式碼塊被synchronized修飾了,當一個執行緒獲取了對應的鎖,執行程式碼塊時,其他執行緒 便只能一直等待,等待獲取鎖的執行
java第18天----生產者消費者,Lock鎖,守護執行緒,join()方法
昨天知識總結: 多執行緒 執行緒的兩種建立方式 建立Thread的子類 執行緒與任務分離 執行緒安全----重點 單例中執行緒安全的應用 執行緒的停止 執行緒 執行緒的通訊 執行緒的通訊: 分析: 需要兩個執行緒—輸入執行緒,和輸
C語言高階篇 - 4.連結串列&狀態機與多執行緒
1.連結串列的引入 1、從陣列的缺陷說起 (1)陣列有2個缺陷,一個是陣列中所有元素的型別必須一致;第二個是陣列的元素個數必須事先制定並且一旦指定之後不能更改。 (2)如何解決
多執行緒:死鎖,樂觀鎖,悲觀鎖
死鎖: 兩個或者多個程序競爭統一資源而形成的僵持的局面,若無外力作用,將無法推進。 本質原因: 1)系統資源有限 2)程序推進順序不合理 死鎖的條件: (1)互斥。某個資源在一段時間只能有一個程序佔有,只有當使用該資源的程序釋放後,其他程序才能佔有該資源。 (2
多執行緒與高併發基礎一(超發--悲觀鎖,樂觀鎖)
關鍵詞: 執行緒,同步,單例,高併發,高訪問,死鎖 一、大規模併發帶來的挑戰 在過去的工作中,我曾經面對過5w每秒的高併發秒殺功能,在這個過程中,整個Web系統遇到了很多的問題和挑戰。如果Web系統不做針對性的優化,會輕而易舉地陷入到異常狀態。我們現在一起來討論下
-1-5 java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒組 執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖 sleep()和wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在O
本文關鍵詞: java 多執行緒 概念 程序 執行緒區別聯絡 java建立執行緒方式 執行緒組 執行緒池概念 執行緒安全 同步 同步程式碼塊 Lock鎖 sleep()和wait()方法的區別 為什麼wait(),notify(),notifyAll()等方法都定義在Object類中 多執行緒
Java多執行緒的死鎖,活鎖,飢餓
死鎖:是指兩個或兩個以上的程序(或執行緒)在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。 死鎖發生在當一些程序請求其他程序佔有的資源而被阻塞時。 死鎖發
多執行緒同步理解(二)——lock鎖方式
上篇文章,已經提了同步鎖的synchronized的物件鎖和類鎖。這一節我決定研究lock鎖的實現方式。lock鎖可以做到執行緒同步,也就是在多執行緒裡面實現加鎖,同步。 一、同一個物件同步鎖的區域性lock。 為同一個物件呼叫同一個方法的時候
執行緒同步(執行緒安全處理Synchronized)與死鎖
一 執行緒同步 java中提供了執行緒同步機制,它能夠解決上述的執行緒安全問題。 執行緒同步的方式有兩種: 方式1:同步程式碼塊 方式2:同步方法 1 同步程式碼塊 同步程式
1執行緒同步:互斥量,死鎖
1執行緒為什麼要同步 A:共享資源,多個執行緒都可對共享資源操作。 B:執行緒操作共享資源的先後順序不確定。 C:處理器對儲存器的操作一般不是原子操作。 2互斥量 mutex操作原語
mysql 開發進階篇系列 14 鎖問題(避免死鎖,死鎖查看分析)
mysq cit 優化 業務流程 update span tro isp 問題 一. 概述 通常來說,死鎖都是應用設計問題,通過調整業務流程,數據庫對象設計,事務大小,以及訪問數據庫的sql語句,絕大部分死鎖都可以避免,下面介紹幾種避免死鎖的常用 方法. 1. 在應
對執行緒本地變數的理解,將登入資訊存放到執行緒本地變數中
在獲取使用者的登入資訊時,我們一般從ThreadLocalMap中獲取,ThreadLocalMap中存放的變數就是執行緒本地的變數,是執行緒隔離的,使用執行緒本地變數而非區域性變數的原因:方便我們對這些變數統一管理,免去頻繁地傳參。 ThreadLocal 原
Java多執行緒程式設計-(5)-使用Lock物件實現同步以及執行緒間通訊
前幾篇: 在《Java多執行緒程式設計-(4)-執行緒間通訊機制的介紹與使用》已經學習了,可以使用方法wait/notify 結合同步關鍵字syn
Python實戰之processing程序(多程序,程序池,lock鎖,程序間的通訊)
首先須知 什麼是IO? 從硬碟讀塊資料,從網路讀塊資料屬於IO操作(IO操作不佔用cpu) 計算佔用cpu,如:1+1 Python多執行緒其實就是一個執行緒,由於利用CUP的上下文切換看起來就像是併發..上下文切換消耗資源 Python多執行緒 不適合CPU密集操作型的任務,適
多執行緒:synchronize、volatile、Lock 的區別與用法
Java多執行緒之記憶體可見性和原子性:Synchronized和Volatile的比較 在說明Java多執行緒記憶體可見性之前,先來簡單瞭解一下Java記憶體模型。
程序,執行緒,程式的區別和聯絡
程序和程式區別和聯絡表現在以下方面: 1)程式只是一組指令的有序集合,它本身沒有任何執行的含義,它只是 一個靜態的實體。而程序則不同,它是程式在某個資料集上的執行。 程序是一個動態的實體,它有自己的生命週期。它因建立而產生,因 排程而執行,因等待資源或事件而被處於等待
Spark修煉之道(高階篇)——Spark原始碼閱讀:第八節 Task執行
Task執行 在上一節中,我們提到在Driver端CoarseGrainedSchedulerBackend中的launchTasks方法向Worker節點中的Executor傳送啟動任務命令,該命令的接收者是CoarseGrainedExecutorBack
synchronized實現原理及其優化-(自旋鎖,偏向鎖,輕量鎖,重量鎖)
1.synchronized概述: synchronized修飾的方法或程式碼塊相當於併發中的臨界區,即在同一時刻jvm只允許一個執行緒進入執行。synchronized是通過鎖機制實現同一時刻只允許一個執行緒來訪問共享資源的。另外synchronized鎖機制還可以保證執行緒併發執行的原子性,有序性,可
C# lock 語法糖實現原理--《.NET Core 底層入門》之自旋鎖,互斥鎖,混合鎖,讀寫鎖
在多執行緒環境中,多個執行緒可能會同時訪問同一個資源,為了避免訪問發生衝突,可以根據訪問的複雜程度採取不同的措施 原子操作適用於簡單的單個操作,無鎖演算法適用於相對簡單的一連串操作,而執行緒鎖適用於複雜的一連串操作 ### 原子操作 修改狀態要麼成功且狀態改變,要麼失敗且狀態不變,並且外部只能觀察到修改
<Linux> 文件夾右下角有鎖,解鎖
text https href user targe vps amp 路徑 pyw sudo chown -R $USER 文件夾路徑 例如:sudo chown -R $USER ~/scala<Linux> 文件夾右下角有鎖,解鎖