synchronized 與 Lock 的那點事

synchronized 與 Lock 的那點事

最近在做一個監控系統,該系統主要包括對數據實時分析和存儲兩個部分,由于并發量比較高,所以不可避免的使用到了一些并發的知識。為了實現這些要求,后臺使用一個隊列作為緩存,對于請求只管往緩存里寫數據。同時啟動一個線程監聽該隊列,檢測到數據,立即請求調度線程,對數據進行處理。 具體的使用方案就是使用同步保證數據的正常,使用線程池提高效率。

同步的實現當然是采用鎖了,java中使用鎖的兩個基本工具是 synchronized 和 Lock。
一直很喜歡synchronized,因為使用它很方便。比如,需要對一個方法進行同步,那么只需在方法的簽名添加一個synchronized關鍵字。
// 未同步的方法
public void test() {}
// 同步的方法
pubilc synchronized void test() {}
synchronized 也可以用在一個代碼塊上,看
public void test() {
synchronized(obj) {
System.out.println("===");
}
}
synchronized 用在方法和代碼塊上有什么區別呢?
synchronized 用在方法簽名上(以test為例),當某個線程調用此方法時,會獲取該實例的對象鎖,方法未結束之前,其他線程只能去等待。當這個方法執行完時,才會釋放對象鎖。其他線程才有機會去搶占這把鎖,去執行方法test,但是發生這一切的基礎應當是所有線程使用的同一個對象實例,才能實現互斥的現象。否則synchronized關鍵字將失去意義。
但是如果該方法為類方法,即其修飾符為static,那么synchronized 意味著某個調用此方法的線程當前會擁有該類的鎖,只要該線程持續在當前方法內運行,其他線程依然無法獲得方法的使用權!
synchronized 用在代碼塊的使用方式:synchronized(obj){//todo code here}
當線程運行到該代碼塊內,就會擁有obj對象的對象鎖,如果多個線程共享同一個Object對象,那么此時就會形成互斥!特別的,當obj == this時,表示當前調用該方法的實例對象。即
public void test() {
...
synchronized(this) {
// todo your code
}
...
}
此時,其效果等同于
public synchronized void test() {
// todo?your code
}
使用synchronized代碼塊,可以只對需要同步的代碼進行同步,這樣可以大大的提高效率。
小結:
使用synchronized 代碼塊相比方法有兩點優勢:
1、可以只對需要同步的使用
2、與wait()/notify()/nitifyAll()一起使用時,比較方便
----------------------------------------------------------------------------------------------------------------------------------------------------------
wait() 與notify()/notifyAll()
這三個方法都是Object的方法,并不是線程的方法!
wait():釋放占有的對象鎖,線程進入等待池,釋放cpu,而其他正在等待的線程即可搶占此鎖,獲得鎖的線程即可運行程序。而sleep()不同的是,線程調用此方法后,會休眠一段時間,休眠期間,會暫時釋放cpu,但并不釋放對象鎖。也就是說,在休眠期間,其他線程依然無法進入此代碼內部。休眠結束,線程重新獲得cpu,執行代碼。wait()和sleep()最大的不同在于wait()會釋放對象鎖,而sleep()不會!
notify(): 該方法會喚醒因為調用對象的wait()而等待的線程,其實就是對對象鎖的喚醒,從而使得wait()的線程可以有機會獲取對象鎖。調用notify()后,并不會立即釋放鎖,而是繼續執行當前代碼,直到synchronized中的代碼全部執行完畢,才會釋放對象鎖。JVM則會在等待的線程中調度一個線程去獲得對象鎖,執行代碼。需要注意的是,wait()和notify()必須在synchronized代碼塊中調用
notifyAll()則是喚醒所有等待的線程。
為了說明這一點,舉例如下:
兩個線程依次打印"A""B",總共打印10次。
public?class?Consumer?implements?Runnable {
@Override
public?synchronized?void?run() {
//?TODO?Auto-generated method stub
int?count = 10;
while(count > 0) {
synchronized?(Test.?obj) {
System.?out.print(?"B");
count --;
Test.?obj.notify();?// 主動釋放對象鎖
try?{
Test.?obj.wait();
}?catch?(InterruptedException e) {
//?TODO?Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public?class?Produce?implements?Runnable {
@Override
public?void?run() {
//?TODO?Auto-generated method stub
int?count = 10;
while(count > 0) {
synchronized?(Test.?obj) {
//System.out.print("count = " + count);
System.?out.print(?"A");
count --;
Test.?obj.notify();
try?{
Test.?obj.wait();
}?catch?(InterruptedException e) {
//?TODO?Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
測試類如下:
public?class?Test {
public?static?final?Object?obj?=?new?Object();
public?static?void?main(String[] args) {
new?Thread(?new?Produce()).start();
new?Thread(?new?Consumer()).start();
}
}
這里使用static obj作為鎖的對象,當線程Produce啟動時(假如Produce首先獲得鎖,則Consumer會等待),打印“A”后,會先主動釋放鎖,然后阻塞自己。Consumer獲得對象鎖,打印“B”,然后釋放鎖,阻塞自己,那么Produce又會獲得鎖,然后...一直循環下去,直到count = 0.這樣,使用Synchronized和wait()以及notify()就可以達到線程同步的目的。
----------------------------------------------------------------------------------------------------------------------------------------------------------
?
除了wait()和notify()協作完成線程同步之外,使用Lock也可以完成同樣的目的。
?
ReentrantLock 與synchronized有相同的并發性和內存語義,還包含了中斷鎖等候和定時鎖等候,意味著線程A如果先獲得了對象obj的鎖,那么線程B可以在等待指定時間內依然無法獲取鎖,那么就會自動放棄該鎖。
但是由于synchronized是在JVM層面實現的,因此系統可以監控鎖的釋放與否,而ReentrantLock使用代碼實現的,系統無法自動釋放鎖,需要在代碼中finally子句中顯式釋放鎖lock.unlock();
同樣的例子,使用lock 如何實現呢?
public?class?Consumer?implements?Runnable {
private?Lock?lock;
public?Consumer(Lock lock) {
this.?lock?= lock;
}
@Override
public?void?run() {
//?TODO?Auto-generated method stub
int?count = 10;
while( count > 0 ) {
try?{
lock.lock();
count --;
System.?out.print(?"B");
}?finally?{
lock.unlock(); //主動釋放鎖
try?{
Thread.?sleep(91L);
}?catch?(InterruptedException e) {
//?TODO?Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public?class?Producer?implements?Runnable{
private?Lock?lock;
public?Producer(Lock lock) {
this.?lock?= lock;
}
@Override
public?void?run() {
//?TODO?Auto-generated method stub
int?count = 10;
while?(count > 0) {
try?{
lock.lock();
count --;
System.?out.print(?"A");
}?finally?{
lock.unlock();
try?{
Thread.?sleep(90L);
}?catch?(InterruptedException e) {
//?TODO?Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
調用代碼:
public?class?Test {
public?static?void?main(String[] args) {
Lock lock =?new?ReentrantLock();
Consumer consumer =?new?Consumer(lock);
Producer?producer?=?new?Producer(lock);
new?Thread(consumer).start();
new?Thread(?producer).start();
}
}
使用建議:
在并發量比較小的情況下,使用synchronized是個不錯的選擇,但是在并發量比較高的情況下,其性能下降很嚴重,此時ReentrantLock是個不錯的方案。

轉載于:https://www.cnblogs.com/handsome1013/p/7299394.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391779.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391779.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391779.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ols線性回歸_普通最小二乘[OLS]方法使用于機器學習的簡單線性回歸變得容易

ols線性回歸Hello Everyone!大家好! I am super excited to be writing another article after a long time since my previous article was published.自從上一篇文章發表很長時間以來,我很高興能寫另一篇文章。 A Simple Linear Regression [SLR] is…

ubuntu安裝配置jdk

先去 Oracle下載Linux下的JDK壓縮包,我下載的是jdk-7u4-linux-i586.tar.gz文件,下好后直接解壓Step1:# 將解壓好的jdk1.7.0_04文件夾用最高權限復制到/usr/lib/jvm目錄里sudo cp -r ~/jdk1.7.0_04/ /usr/lib/jvm/Step2:# 配置環境變量sudo gedit ~/.prof…

leetcode 697. 數組的度(hashmap)

給定一個非空且只包含非負數的整數數組 nums,數組的度的定義是指數組里任一元素出現頻數的最大值。 你的任務是在 nums 中找到與 nums 擁有相同大小的度的最短連續子數組,返回其長度。 示例 1: 輸入:[1, 2, 2, 3, 1] 輸出&…

facebook機器學習_如何為您的頁面創建Facebook Messenger機器人

facebook機器學習by Paul Pinard保羅皮納德(Paul Pinard) 如何為您的頁面創建Facebook Messenger機器人 (How to create a Facebook messenger bot for your page) When it comes to sharing your chatbot, Facebook Messenger is a must. We created a very easy step-by-ste…

Logstash配置語法及相關命令

配置結構以及插件位置 輸入插件: input{ … } 過濾插件: filter{ … } 輸出插件: output{ … } 數據類型 - Array users > [{id > 1,name > N1},{id > 2,name > N2}] - lists path > ["/var/log/messages"…

面試整理

SpringMVC 和Struts2的區別 1. 機制: spring mvc的入口是servlet,而struts2是filter,這樣就導致了二者的機制不同。 2. 性能: spring會稍微比struts快。spring mvc是基于方法的設計,而sturts 是基于類,…

Amazon Personalize:幫助釋放精益數字業務的高級推薦解決方案的功能

By Gerd Wittchen蓋德維琴 推薦解決方案的動機 (Motivation for recommendation solutions) Rapid changes in customer behaviour requires businesses to adapt at an ever increasing pace. The recent changes to our work and personal life has forced entire nations t…

Linux 鏈接文件講解

鏈接文件是Linux文件系統的一個優勢。如需要在系統上維護同一文件的兩份或者多份副本,除了保存多份單獨的物理文件之外,可以采用保留一份物理文件副本和多個虛擬副本的方式,這種虛擬的副本就成為鏈接。鏈接是目錄中指向文件真實位置的占位符。…

系統滾動條實現的NUD控件Unusable版

昨天研究了一下系統滾動條,準備使用它來實現一個NumericUpDown控件,因為它可以帶來最正宗的微調按鈕外觀,并說了一下可以使用viewport里的onScroll事件來獲取系統滾動條的上下點擊動作。 同時昨天還說了onScroll事件的一個問題是&#xf…

react 中渲染html_如何在React中識別和解決浪費的渲染

react 中渲染htmlby Nayeem Reza通過Nayeem Reza 如何在React中識別和解決浪費的渲染 (How to identify and resolve wasted renders in React) So, recently I was thinking about performance profiling of a react app that I was working on, and suddenly thought to set…

php變量的數據類型

一、類型 標量類型: 布爾型 整型 浮點型 字符串 復合類型: 數組 對象 特殊類型: 資源 null 1. 布爾型 true false 以下值認為是false 其他值都認為是true; 布爾值false 整型值0 浮點的0 空字符串和字符串0 空數組 空對象(只適用于php4) 特殊類型null 2. 整型 正整數和負整…

[習題].FindControl()方法 與 PlaceHolder控件 #2(動態加入「子控件」的事件)

這是我的文章備份,有空請到我的網站走走, http://www.dotblogs.com.tw/mis2000lab/ 才能掌握我提供的第一手信息,謝謝您。 http://www.dotblogs.com.tw/mis2000lab/archive/2011/07/26/placeholder_findcontrol_eventhandler.aspx [習題].Fi…

西雅圖治安_數據科學家對西雅圖住宿業務的分析

西雅圖治安介紹 (Introduction) Airbnb provides an online platform for hosts to accommodate guests with short-term lodging. Guests can search for lodging using filters such as lodging type, dates, location, and price, and can search for specific types of hom…

leetcode 1438. 絕對差不超過限制的最長連續子數組(滑動窗口+treemap)

給你一個整數數組 nums ,和一個表示限制的整數 limit,請你返回最長連續子數組的長度,該子數組中的任意兩個元素之間的絕對差必須小于或者等于 limit 。 如果不存在滿足條件的子數組,則返回 0 。 示例 1: 輸入&#…

react-redux圖解_如何將React連接到Redux —圖解指南

react-redux圖解by Princiya由Princiya 如何將React連接到Redux —圖解指南 (How to connect React to Redux — a diagrammatic guide) This post is aimed at people who already know React and Redux. This will aid them in better understanding how things work under …

幾種機器學習算法的優缺點

1決策樹(Decision Trees)的優缺點 決策樹的優點: 一、 決策樹易于理解和解釋.人們在通過解釋后都有能力去理解決策樹所表達的意義。 二、 對于決策樹,數據的準備往往是簡單或者是不必要的.不需要預處理數據。…

【貪心】買賣股票的最佳時機含手續費

/** 貪心:每次選取更低的價格買入,遇到高于買入的價格就出售(此時不一定是最大收益)。* 使用buy表示買入股票的價格和手續費的和。遍歷數組,如果后面的股票價格加上手續費* 小于buy,說明有更低的買入價格更新buy。如…

本科畢設論文——基于Kinect的拖拉機防撞系統

基于Kinect的拖拉機防撞系統電子信息科學與技術專業學生 sukeysun 摘要:隨著智能車輛技術的發展,智能導航定位和實時車載監控等技術被更多的應用到日常生活照。在農業領域上,車輛自主感知道路環境并制定實時避障策略還存在不足,特…

排序算法Java代碼實現(二)—— 冒泡排序

本篇內容: 冒泡排序冒泡排序 算法思想: 冒泡排序的原理是:從左到右,相鄰元素進行比較。 每次比較一輪,就會找到序列中最大的一個或最小的一個。這個數就會從序列的最右邊冒出來。 代碼實現: /*** */ packag…

創意產品 分析_使用聯合分析來發展創意

創意產品 分析Advertising finds itself in a tenacious spot these days serving two masters: creativity and data.如今,廣告業處于一個頑強的位置,服務于兩個大師:創造力和數據。 On the one hand, it values creativity; and it’s not…