`

Concurrent - 锁

    博客分类:
  • Lock
 
阅读更多

原创转载请注明出处:http://agilestyle.iteye.com/blog/2356898

 

什么是可重入锁(ReentrantLock)?


Java多线程中可以使用synchronized关键字来实现线程之间的同步互斥,但在JDK1.5中新增加了ReentrantLock类也能达到同样的效果,并且在扩展功能上也更加强大,比如 嗅探锁定、多路分支通知等功能

ReentrantLock并不是替代synchronized的方法,而是当synchronized不适用时,作为一种可选的高级功能;

从代码上尽量用synchronized,jvm会对synchronized做一定的优化,并且代码可维护和稳定。只有在需要ReentrantLock的一些特性时,可以考虑用ReentrantLock实现。

 

当一个线程进入某个对象的一个synchronized的实例方法后,其它线程是否可进入此对象的其它方法?

可进入非synchronized方法

 

synchronized和java.util.concurrent.locks.Lock的异同?

  • synchronized相当于整个Lock对象中只有一个单一的Condition对象,所有的线程都注册在它一个对象身上;synchronized无法中断一个正在等待获得锁的线程,也即多线程竞争一个锁时,其余未得到锁的线程只能不停的尝试获得锁,而不能中断。这种情况对于大量的竞争线程会造成性能的下降等后果。
  • Lock对象可以创建多个Condition(即对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择性地进行通知,在调度线程上更加灵活。

所以在synchronized无法满足需求的情况下,Lock可以作为一种高级工具,这些功能包括“可定时的、可轮询的与可中断的锁获取操作,公平队列,以及非块结构的锁”否则还是优先使用synchronized 

 

乐观锁和悲观锁的理解及如何实现,有哪些实现方式?

乐观锁 —— CAS

悲观锁 —— mutex

Note:

数据库方面

乐观锁 —— version字段

悲观锁 —— for update

 

如何实现乐观锁(CAS)?如何避免ABA问题?

ABA问题。因为CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。

 

ABA问题的解决思路就是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A 就会变成1A - 2B-3A。

 

从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。

http://ifeve.com/atomic-operation/

 

读写锁可以用于什么应用场景?

http://ifeve.com/read-write-locks/

 

什么时候应该使用可重入锁?

若一个程序或子程序可以“安全的被并行执行(Parallel computing)”,则称其为可重入(reentrant或re-entrant)的。即当该子程序正在运行时,可以再次进入并执行它(并行执行时,个别的执行结果,都符合设计时的预期)。可重入概念是在单线程操作系统的时代提出的。

场景1:如果发现该操作已经在执行中则不再执行(有状态执行)

private ReentrantLock lock = new ReentrantLock();
...
if (lock.tryLock()) { // 如果已经被lock,则立即返回false不会等待,达到忽略操作的效果
	try {
		// 操作
	} finally {
		lock.unlock();
	}
}

场景2:如果发现该操作已经在执行,等待一个一个执行(同步执行,类似synchronized)

private ReentrantLock lock = new ReentrantLock(); // 参数默认false,不公平锁
private ReentrantLock lock = new ReentrantLock(true); // 公平锁
...
try {
	lock.lock(); // 如果被其它资源锁定,会在此等待锁释放,达到暂停的效果
	// 操作
} finally {
	lock.unlock();
}

场景3:如果发现该操作已经在执行,则尝试等待一段时间,等待超时则不执行(尝试等待执行)

private ReentrantLock lock = new ReentrantLock(); // 参数默认false,不公平锁
...
try {
	if (lock.tryLock(5, TimeUnit.SECONDS)) { // 如果已经被lock,尝试等待5s,看是否可以获得锁,如果5s后仍然无法获得锁则返回false继续执行
		try {
			// 操作
		} finally {
			lock.unlock();
		}
	}
} catch (InterruptedException e) {
	e.printStackTrace(); // 当前线程被中断时(interrupt),会抛InterruptedException
}

场景4:如果发现该操作已经在执行,等待执行。这时可中断正在进行的操作立刻释放锁继续下一操作

private ReentrantLock lock = new ReentrantLock(); // 参数默认false,不公平锁
...
try {
    lock.lockInterruptibly();
    //操作
} catch (InterruptedException e) {
    e.printStackTrace();
} finally {
    lock.unlock();
}

   

什么场景下可以使用volatile替换synchronized? 

关键字volatile的主要作用是使变量在多个线程间可见,但无法保证原子性,对于多个线程访问同一个实例变量需要加锁进行同步。

volatile和synchronized区别:

  • volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰变量,synchronized可以修饰方法,以及代码块(JVM新版本发布,synchronized关键字在执行效率上有大提升,在开发中使用synchronized关键字的比率还是比较大的)
  • 多线程访问volatile不会发生阻塞,而synchronized会出现阻塞
  • volatile能保证数据的可见性,但不能保证原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存的数据做同步
  • volatile解决的是变量在多个线程之间的可见性;而synchronized解决的是多个线程之间的访问资源的同步性

 

 

  • 大小: 91.7 KB
分享到:
评论

相关推荐

    concurrent-1.3.4.jar

    原子操作:concurrent包提供了一些原子操作类,如AtomicInteger、AtomicLong等,可以实现无锁的线程安全操作,避免了使用锁带来的性能损耗。 线程池:concurrent包提供了Executor框架,可以方便地创建和管理线程池,...

    java8源码-java-high-concurrent-programming:《实战Java高并发程序设计》

    java-high-concurrent-programming 《实战Java高并发程序设计》源码整理,github上已经有人整理了,但是最近在看这本书,还是自己把每章代码整理下,也加深下自己的理解. 目录 第一章:走入并行世界 第二章:Java...

    java-concurrent-source:Java多并发编程从入门到精通源码-源码通

    java-concurrent-source Java多并发编程从入门到精通源码 第一部分:线程并发基础第1章概念部分1.1 CPU核心数,线程数1.2 CPU时间片轮转机制1.3什么是进程和什么是线程1.4进程与线程比对1.5什么是并行运行1.6什么是...

    lmn-concurrent-hashmap:用于并行模型检查的高性能并发哈希表 C 库

    lmn-concurrent-hashmap 用于并行模型检查的高性能并发哈希映射的 C/C++ 库 要求 autoconf 2.69 automake 1.11.3 gcc 4.6.3 g++ 4.6.3 如何构建 $ autoreconf -i $ ./configure $ make 内容 细粒度锁 ChainHash ...

    java并发工具包 java.util.concurrent中文版用户指南pdf

    1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...

    cpp-concurrent-traffic-sim:Udacity并发流量模拟器

    使用您对并发编程(例如互斥锁,锁和消息队列)的知识来实现​​交通信号灯并将其正确集成到代码库中。 本地运行的依赖项 cmake> = 2.8 所有操作系统: make> = 4.1(Linux,Mac),3.81(Windows) Linux:大多数...

    Concurrent-Traffic-Simulation

    使用您对并发编程(例如互斥锁,锁和消息队列)的知识来实现​​交通信号灯并将其正确集成到代码库中。 本地运行的依赖项 cmake> = 2.8 所有操作系统: make> = 4.1(Linux,Mac),3.81(Windows) Linux:大多数...

    CppND-Program-a-Concurrent-Traffic-Simulation

    使用您对并发编程(例如互斥锁,锁和消息队列)的知识来实现​​交通信号灯并将其正确集成到代码库中。 本地运行的依赖项 cmake> = 2.8 所有操作系统: make> = 4.1(Linux,Mac),3.81(Windows) Linux:大多数...

    Java并发工具包java.util.concurrent用户指南中英文对照阅读版.pdf

    java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...

    Concurrent-DS:基于锁的无锁并发数据结构的源代码-Locking source code

    并发DS 基于锁的无锁并发数据结构的源代码

    Java并发工具包java.util.concurrent用户指南中英文对照阅读版

    本资源包含两个 pdf 文档,一本根据 Jakob Jenkov 最新博客 (http://tutorials.jenkov.com/java-util-concurrent/index.html) 整理的 java_util_concurrent_user_guide_en.pdf,一个中文翻译的 java_util_concurrent...

    concurrent-airport-simulator:用 C# 编写的机场模拟器来演示并发性

    C#中的并发机场模拟器用 C# 编写的机场模拟器,用于演示并发性。 该应用程序使用并发概念,如多线程、锁、信号量等......该项目已从 Microsoft Visual Studio 2013 创建。

    Concurrent-Traffic-Simulation:这是[Udacity C ++纳米学位计划](https

    使用您对并发编程(例如互斥锁,锁和消息队列)的知识来实现​​交通信号灯并将其正确集成到代码库中。 本地运行的依赖项 cmake> = 2.8 所有操作系统: make> = 4.1(Linux,Mac),3.81(Windows) Linux:大多数...

    concurrentqueue, 一种快速多消费者多消费者锁空闲并发队列.zip

    concurrentqueue, 一种快速多消费者多消费者锁空闲并发队列 moodycamel::ConcurrentQueue面向 C 的工业强度锁自由队列。注意:如果你只需要一个生产者,单个消费者队列,我有其中的一个太多。特性Knock-your-socks-...

    concurrent-player

    的确,同步块中的锁在此锁上,而不是在单独的对象上。 #### 使用常规的ReentrantLock实现。 明确使用Lock对象。 优点是可以更灵活地使用锁。 您始终可以在finally部分中保存系统的正确状态。 您可以尝试以不成功的...

    concurrent 多线程 教材

    j-concurrent 00 IBM developerWorks 中国 : Java 多线程与并发编程专题 02 Java 程序中的多线程 03 编写多线程的 Java 应用程序 04 如果我是国王:关于解决 Java编程语言线程问题的建议 (2) 05 构建Java并发...

    parallel-map:用于go的线程安全并发映射

    concurrent-map通过以最少的等待锁时间来分片映射,从而为此提供了一种高性能的解决方案。 在Go 1.9之前,stdlib中没有并发映射实现。 在Go 1.9中,引入了sync.Map 。 新的sync.Map与该映射有一些关键区别。 ...

    java并发工具包详解

    1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...

    javaconcurrent源码-java7-source-code:Java7源码/Concurrency同步

    concurrent源码 Java7 核心类库源码解析 请直接查看.java : 通过JavaDoc+Test书写 ,方便链接到源码 Tracker 20181014 Java11正式发布并作为新的长期支持版本, 未来的应用会逐步迁移到Java11. 因此Java8以前的API参考...

    java并发包资源

    本资源包含两个 pdf 文档,一本根据 Jakob Jenkov 最新博客 (http://tutorials.jenkov.com/java-util-concurrent/index.html) 整理的 java_util_concurrent_user_guide_en.pdf,一个中文翻译的 java_util_concurrent...

Global site tag (gtag.js) - Google Analytics