1. 程式人生 > >synchronized關鍵字、ReentrantLock與原子類比較

synchronized關鍵字、ReentrantLock與原子類比較

我們先比較ReentrantLock與synchronized的用法 1、ReentrantLock擁有synchronized相同的併發性和記憶體語義,此外還多了鎖投票,定時鎖等候和中斷等候。執行緒A和B都要獲取物件O的鎖定,假設A獲取了物件O鎖,B將等待A釋放對O的鎖定。
使用synchronized時,如果A不釋放,B將一直等待下去,無法中斷。
使用ReentrantLock時,如果A不釋放,B可以在等待足夠長時間後,停止等待,繼續執行其他事務。 ReentrantLock獲取鎖定的三種方式:
lock(),如果獲取了鎖立即返回,如果別的執行緒持有鎖,當前執行緒則一直處於休眠狀態,直至獲取鎖。
tryLock(),如果獲取了鎖立即返回true,如果別的執行緒下持有,立即返回false;
tryLock(long timeout, TimeUnit unit),如果獲取了鎖定立即返回true,如果別的執行緒正持有鎖,將等待引數給定的時間,在等待的過程中,如果獲取了鎖定,返回true,如果等待超時,返回false,所以lock()方法相當trylock傳遞個無限大的時間引數;
lockInteruptibly,如果獲取了鎖定立即返回,反之,當前執行緒處理休眠,直至獲取鎖,或者當前執行緒執行緒被其他執行緒中斷。 2、synchronized是在JVM層面實現,不但可以通過一些監控工具監控鎖定,而且在程式碼執行出現異常,JVM自動釋放鎖定;
Lock是通過程式碼實現,為了保證鎖定一定會被釋放,一般會將unLock()放到flyinal{}中。 3、在資源競爭不激烈的情況下,synchronized的效能要優於ReentrantLock,但在資源競爭很激烈的情況下,synchronized的效能會下降幾十倍(jvm需要分配額外的cpu和記憶體來管理同步),但是ReentrantLock的效能能維持常態。 ReentrantLock例子如下:
package test.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockTest1 extends Thread {

	private int threadNo;
	private static Lock lock = new ReentrantLock();

	public LockTest1(int threadNo) {
		this.threadNo = threadNo;
	}

	public static void main(String[] args) throws InterruptedException {
		for (int i = 0; i < 10; i++) {
			new LockTest1(i).start();
		}
	}

	@Override
	public void run() {
		lock.lock();
		try {
			for (int i = 0; i < 100; i++) {
				System.out.println("No." + (threadNo + 1) + ": " + (i + 1));
			}
		} finally {
			lock.unlock();
		}
	}
}
下面討論原子類: synchronized關鍵字、Lock可以控制程式片段的同步,原子類只能保證單個變數的同步。執行緒競爭不激烈時,原子類效能比synchronized略低,當競爭激烈時,也能維持常態。 下面是一個多執行緒共同計數的程式碼程式碼。
package test.lock;


public class LockTest2 extends Thread {

	private static int race = 0;
	private int threadNo;

	public LockTest2(int threadNo) {
		this.threadNo = threadNo;
	}

	public static void main(String[] args) throws InterruptedException {
		for (int i = 0; i < 10; i++) {
			new LockTest2(i).start();
		}

		while (Thread.activeCount() > 1) {
			Thread.yield();
		}
		System.out.println(race);
	}

	@Override
	public void run() {
		for (int i = 0; i < 1000; i++) {
			race++;
		}
	}
}
上面程式執行後,並沒有得到期望的原子類。我們用ActomicInteger實現程式碼如下:
package test.lock;

import java.util.concurrent.atomic.AtomicInteger;

public class LockTest2 extends Thread {

	private static AtomicInteger race = new AtomicInteger();
	private int threadNo;

	public LockTest2(int threadNo) {
		this.threadNo = threadNo;
	}

	public static void main(String[] args) throws InterruptedException {
		for (int i = 0; i < 10; i++) {
			new LockTest2(i).start();
		}

		while (Thread.activeCount() > 1) {
			Thread.yield();
		}
		System.out.println(race);
	}

	@Override
	public void run() {
		for (int i = 0; i < 1000; i++) {
			race.addAndGet(1);
		}
	}
}

相關推薦

synchronized關鍵字ReentrantLock原子比較

我們先比較ReentrantLock與synchronized的用法 1、ReentrantLock擁有synchronized相同的併發性和記憶體語義,此外還多了鎖投票,定時鎖等候和中斷等候。執行緒A和B都要獲取物件O的鎖定,假設A獲取了物件O鎖,B將等待A釋放對O的鎖定

Android進階——多執行緒系列之waitnotifysleepjoinyieldsynchronized關鍵字ReentrantLock

前言 多執行緒一直是初學者最困惑的地方,每次看到一篇文章,覺得很有難度,就馬上叉掉,不看了,我以前也是這樣過來的。後來,我發現這樣的態度不行,知難而退,永遠進步不了。於是,我狠下心來看完別人的部落格,儘管很難但還是咬著牙,不懂去查閱資料,到最後弄懂整個過程。雖

equalsHashCode實體的設計

public 相同 不用 java 元素 avi 沒有 設計 sta equals和HashCode都是用來去重的,即判斷兩個對象是否相等。如果是String類則我們直接用.equals()判斷,如果是我們自己定義的類,需要有自己的判斷方

【C/C++開發】C++之enum列舉量宣告定義使用列舉詳解列舉前置型別宣告

前面講到可以通過強制轉換將其他型別值賦給列舉變數:Weekday = enumType(2);這是合法的;但是Weekday = enumType(20);是非法的。這裡涉及列舉取值範圍的概念:列舉的上限是 大於最大列舉量的 最小的2的冪,減去1; 列舉的下限有兩種情況:一、列舉量的最小值不小於0,則列

迴歸分類:三大方向剖解機器學習演算法的優缺點

在本教程中,作者對現代機器學習演算法進行一次簡要的實戰梳理。雖然類似的總結有很多,但是它們都沒有真正解釋清楚每個演算法在實踐中的好壞,而這正是本篇梳理希望完成的。因此本文力圖基於實踐中的經驗,討論每個演算法的優缺點。而機器之心也在文末給出了這些演算法的具體實現細節。 對機器學習演算法進行分類不是一

Java多執行緒(二)之Atomic:原子變數原子

一、何謂Atomic?  Atomic一詞跟原子有點關係,後者曾被人認為是最小物質的單位。計算機中的Atomic是指不能分割成若干部分的意思。如果一段程式碼被認為是Atomic,則表示這段程式碼在

C++虛擬函式JAVA中抽象函式比較 介面抽象比較

C++虛擬函式與Java中抽象函式比較 1:java中沒有虛擬函式的概念,但是有抽象函式的概念,用abstract關鍵字表示,java中抽象函式必須在抽象類中,而且抽象 函式不能有函式體,抽象類不能被例項化,只能由其子類實現抽象函式,如果某個抽象類的子類仍是抽象類,那麼該子

C++之enum列舉量宣告定義使用列舉詳解

前面講到可以通過強制轉換將其他型別值賦給列舉變數:Weekday = enumType(2);這是合法的;但是Weekday = enumType(20);是非法的。這裡涉及列舉取值範圍的概念:列舉的上限是 大於最大列舉量的 最小的2的冪,減去1; 列舉的下限有兩種情況:一、列舉量的最小值不小於0,則列

判斷變數是否不為空,函式isset()!empty()!is_null()的比較

判斷變數的值,尤其是判斷他們是否不為空,我們有以下4種方法: if(isset($test)) true:變數已被賦值/設定 if(!empty($test)) true:變數不為空 if(!is_null($test)) true:變數不為空 if($

前端框架學習總結之AngularReactVue的比較詳解

近幾年前端的技術發展很快,細分下來,主要可以分成四個方面: 1.開發語言技術,主要是ES6&7,coffeescript,typescript等; 2.開發框架,如Angular,React,Vue.js,Angular2等; 3.開發工具的豐富和前端工程化,像

雲星資料---Scala實戰系列(精品版)】:Scala入門教程016-Scala實戰原始碼-Scala 判斷語句 迴圈java的比較

Scala 判斷語句 、迴圈與java的比較 package scala_learn.demo01_FunctionStatement /** * Created by liguohua on

基礎學習--標識符關鍵字數據運算符

woe air nsh and sld shang lag ngs dac %5Bpython%5D%E8%8E%B7%E5%8F%96%E7%BD%91%E9%A1%B5%E4%B8%AD%E5%86%85%E5%AE%B9%E4%B8%BA%E6%B1%89%E5%AD

Java中的組織形式物件靜態的static關鍵字最終的final關鍵字方法傳參方式遞迴(階乘斐波那契數列漢諾塔)

Java程式的組織形式 Java程式需要把程式碼以類的形式組織起來,然後被Java編譯器編譯,再被JVM執行。Java程式是以類的結構為基礎的。 Java程式的基本要素 識別符號 識別符號命名規範 關鍵字(保留字) 關鍵字(保留字)具有專門的意義和用途

java synchronized關鍵字的用法以及鎖的等級:方法鎖物件鎖

轉載自:http://blog.csdn.net/le_le_name/article/details/52348314 java的內建鎖:每個java物件都可以用做一個實現同步的鎖,這些鎖成為內建鎖。執行緒進入同步程式碼塊或方法的時候會自動獲得該鎖,在退出同步程式碼塊

JAVA final super 關鍵字以及繼承關係中父例項變數初始化的 理解

1,final 修飾符修飾變數、方法、類 時有什麼作用? ①final 修飾變數:該變數被賦初值後,不能對它重新賦值 ②final 修飾方法:此方法不能重寫,即父類中某方法被final修飾,在子類中將不能定義一個與父類final 方法同名且有相同方法識別符號(引數個數也相同

JAVA的synchronized關鍵字concurrent併發包的效能比較

     private static AtomicInteger mySessionID= new AtomicInteger(-2);     public static int getMySessionID() {         return mySessionID

多執行緒經常使用的3個關鍵字synchronizedReentrantLockvolatile

3個關鍵字synchronized、ReentrantLock、volatile。 一、synchronized   互斥鎖,即操作互斥,併發執行緒過來,序列獲得鎖,序列執行程式碼。就像一個房間一把鑰匙,一個人進去後,下一個人得等第一個人出來得到鑰匙才能進入。如果程式

Java併發程式設計---volatile關鍵字atomic原子

一.Volatile關鍵字      1.1 概念            volatile關鍵字的主要作用是使變數在多個執行緒間可見    1.2 示例程式 package com.thread.

對於SynchronizedReentrantLockAtomicCAS在併發下面的效能比較測試

對於Synchronized、ReentrantLock、Atomic、CAS在併發下面的效能比較,在JDK1.6和JDK1.8下面測試通過。 我們考慮一個最簡單的併發場景,對物件自增欄位在併發下面的處理: 介面:Counter public interface Co

Java中的synchronizedvolatileReenTrantLockAtomicXXX

包含 指令 純粹 功能性 title 伸縮 其它 同步問題 留下 多線程和並發性並不是什麽新內容,但是 Java 語言設計中的創新之一就是,它是第一個直接把跨平臺線程模型和正規的內存模型集成到語言中的主流語言。核心類庫包含一個 Thread 類,可以用它來構建、啟動和操縱線