原先多线程并发编程的学习笔记和代码整理一下贴上来。
---------------------------------
synchronized与Lock
Java中提供了2种线程同步的方式,一种是Java语言级的同步原语synchronized关键字,另一种是使用javase5中新提供的java.util.concurrent.locks.Lock相关接口。
一、synchronized
关于synchronized,大家应该都比较熟悉了,从最早的java规范开始就包含了这个关键字。
1、synchronized作用域:
(1)是某个对象实例范围。synchronized防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。但不同对象实例的synchronized方法是不相干扰的,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法。
(2)是某个类的范围。防止多个线程同时访问这个类中的synchronized static方法,它可以对类的所有对象实例起作用。
2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;如果在另一个对象上同步synchronized(other){/*区块*/},就要确保所有相关线程都在同一个对象上同步。
当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){}。在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法。
二、Lock相关接口
对于Lock接口,JDK文档描述如下:
Lock实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作。
Lock接口的实现允许锁在不同的作用范围内获取和释放,并允许以任何顺序获取和释放多个锁,从而支持使用这种技术。
Lock对象必须被显示的创建、锁定和释放,这是与synchronized的区别之一。
1、Lock接口与ReentrantLock:
使用ReentrantLock所需代码比synchronized要多,通常为解决一些特殊问题,如:
synchronized关键字不能尝试着获取锁且最终获取锁会失败,或者尝试着获取锁然后放弃它。
ReentrantLock允许你尝试获取锁并但最终并未获取,synchronized若获取不到锁则会一直阻塞。
举例:首先定义一个task,使用ReentrantLock作为锁。
class LockTask{ private Lock lock=new ReentrantLock(); public Lock getLock(){ return lock; } public void lockA(){ boolean locked=lock.tryLock(); try{ System.out.println("isLocked:"+locked); }finally{ if(locked){ lock.unlock(); } } } public void lockB(){ boolean locked=false; try { locked=lock.tryLock(5, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } try{ System.out.println("isLocked(5s)="+locked); }finally{ if(locked){ lock.unlock(); } } } }
注意lockA和lockB中的tryLock方法,仅在调用时锁未被另一个线程保持的情况下,才获取该锁。如果锁被另一个线程保持,则此方法将立即返回false。 其中lockB设置了tryLock的时间为5s。注意一定要在finally中释放锁。
下面测试时,会打开一个线程获取先lock住锁,之后再调用lockA和B方法。其中Thread.currentThread().join(1000);保证lock操作一定会执行完。
final LockTask task=new LockTask(); task.lockA(); task.lockB(); new Thread(){ {setDaemon(true);} public void run(){ task.getLock().lock(); System.out.println("lock!"); } }.start(); Thread.currentThread().join(1000); task.lockA(); task.lockB();查看输出:
isLocked:true isLocked(5s)=true lock! isLocked:false isLocked(5s)=false可见当已经有线程拿到锁时,再次尝试获取锁会失败(返回false),而synchronized则会一直阻塞等待。
2、ReadWriteLock接口与ReentrantReadWriteLock
java.util.concurrent.locks包中另一个接口是ReadWriteLock读写锁。
关于ReadWriteLock,JDK文档中描述:
ReadWriteLock维护了一对相关的锁,一个用于只读操作,另一个用于写入操作。只要没有writer,读取锁可以由多个reader线程同时保持。写入锁是独占的。
意思就是没有写锁时,读锁可以由多个线程保持,而有写锁只能由一个线程持有。
举例:
定义一个类包含2个方法,read和write。read方法获取读锁,write方法获取写锁。
class ReadWrite{ int data = 1; ReadWriteLock rwl = new ReentrantReadWriteLock(); public void read(){ rwl.readLock().lock(); try{ System.out.println(Thread.currentThread().getName()+" reading..."); Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+" read:" + data); }catch(InterruptedException e){ e.printStackTrace(); }finally{ rwl.readLock().unlock(); } } public void write(int data){ rwl.writeLock().lock(); try{ System.out.println(Thread.currentThread().getName()+" writing..."); this.data = data; Thread.sleep(100); System.out.println(Thread.currentThread().getName()+" written:" + data); }catch(InterruptedException e){ e.printStackTrace(); }finally{ rwl.writeLock().unlock(); Thread.yield();//让步 } } }
上面程序中,让read方法持有锁1s,且只进行读操作打印data值,write方法持有锁的时间稍短一些0.1s,同时进行写操作给data赋值。
进行读写操作:
此处启动3个线程,一个循环写入data随机数,另外2个线程循环读取data值。
final ReadWrite readWrite = new ReadWrite(); new Thread(){ public void run(){ while(true){ readWrite.write(new Random().nextInt(1000)); } } }.start(); Thread.sleep(1000); for(int i=0;i<2;i++){ new Thread(){ public void run() { while(true){ readWrite.read(); } } }.start(); }程序运行后一段时间,可以看到,写数据的时候不能读,读数据的时候不能写,但可以同时2个线程在读。
所以说,写锁是独占的,读锁可以由多个线程保持。
另外,JDK文档中提到另外一个示例:
在使用某些种类的 Collection时,可以使用ReentrantReadWriteLock来提高并发性。通常,在预期 collection很大,读取者线程访问它的次数多于写入者线程,并且entail操作的开销高于同步开销时,这很值得一试。以下是一个使用 TreeMap的类,预期它很大,并且能被同时访问。
class RWDictionary { private final Map<String, Data> m = new TreeMap<String, Data>(); private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); private final Lock w = rwl.writeLock(); public Data get(String key) { r.lock(); try { return m.get(key); } finally { r.unlock(); } } public String[] allKeys() { r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); } } public Data put(String key, Data value) { w.lock(); try { return m.put(key, value); } finally { w.unlock(); } } public void clear() { w.lock(); try { m.clear(); } finally { w.unlock(); } } }使用读锁get数据和获取key,使用写锁put数据和清除map。注意要unlock。
相关推荐
并发编程原理学习:synchronized关键字.doc
Java并发编程系列- synchronized;Java并发编程系列- synchronized;Java并发编程系列- synchronized;
并发编程中,锁是经常需要用到的,今天我们一起来看下Java中的锁机制:synchronized和lock。 Synchronized 和 Lock的概念 Synchronized 是Java 并发编程中很重要的关键字,另外一个很重要的是 volatile。Syncronized...
本文的主题是关于具有java语言风格的Thread、synchronized、volatile,以及J2SE5中新增的概念,如锁(Lock)、原子性(Atomics)、并发集合类、线程协作摘要、Executors。开发者通过这些基础的接口可以构建高并发、线程...
此外,本书还提供了有关并发编程的全方位的详细内容,例如限制和同步、死锁和冲突、依赖于状态的操作控制、异步消息传递和控制流、协作交互,以及如何创建基于web的服务和计算型服务。 本书的读者对象是那些希望掌握...
│ 高并发编程第一阶段18讲、数据同步的引入与Synchronized的简单介绍.mp4 │ 高并发编程第一阶段19讲、结合jconsole,jstack以及汇编指令认识synchronized关键字.mp4 │ 高并发编程第一阶段20讲、同步代码块以及...
Synchronized是Java中解决并发问题的一种常用的方法,也是简单的一种方法。Synchronized的作用主要有三个:(1)确保线程互斥的访问同步代码(2)保证共享变量的修改能够及时可见(3)有效解决重排序问题。从语法...
第二部分引入了ClassLoader,这是因为ClassLoader与线程不无关系,我们可以通过synchronized关键字,或者Lock等显式锁的方式在代码的编写阶段对共享资源进行数据一致性保护,那么一个Class在完成初始化的整个过程到...
一、同步省略 二、将堆分配转化为栈分配 三、分离对象或标量替换
并发编程关键字
07-JUC高并发编程-Lock接口概述和实现案例.mp48 G J/ u; W' _$ o: {2 M 08-JUC高并发编程-线程间通信-概述和案例分析.mp4 09-JUC高并发编程-线程间通信-Synchronized实现案例.mp4 10-JUC高并发编程-线程间通信-虚假...
关联自己的博客《并发编程(一)》中的附件,主要提供一些demo供大家演示和使用,主要涉及一些并发的一些的基本使用,包括synchronized关键字、volatile关键字。
本资源为您提供了关于 Java 并发编程理论基础的精讲,涵盖了多线程编程的核心概念、基本原理以及在 Java 中的应用。通过深入学习,您将建立坚实的并发编程基础,能够更好地理解和应对多线程编程中的挑战。 并发编程...
Java并发编程---synchronized关键
互联网信息泛滥环境下少有的良心之作!如果您想对Java编程synchronized与lock的区别有所了解,这篇文章绝对值得!分享给大家,供需要的朋友参考。不说了,我先学习去了。
java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个...
【多线程与高并发原理篇:4_深入理解synchronized】.doc
Synchronized相关问题 问题一:Synchronized用过吗,其原理是什么? 问 题 二 : 你 刚 才 提 到 获 取 对 象 的 锁 , 这 个 “ 锁 ” 到 底 是 什 么 ? 如 何 确 定 对 象 的 锁 ? 问 题 三 : 什 么 是 可 重 ...
龙果 java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四...
【Java并发编程】Synchronized关键字实现原理.doc