文档章节

Synchronized与Lock

EveryDayNew
 EveryDayNew
发布于 2016/10/02 23:54
字数 1078
阅读 64
收藏 5

Synchronized是并发中使用最频繁的关键字了,它可以使用在方法、代码块上,表示对该段代码加锁,而必须要持有锁才能执行这段代码。Synchronized具有互斥性。

说起来蛮简单,而实际中编程 ,最难得地方有两点

1、确定并发间隙

2、确定锁的对象

做好这两点才能处理好锁的粒度,是并发的性能更好。

eg1、Synchronized加在静态方法上,不同的线程调用这两个方法互斥。此时synchronize锁的是该类

public class SynchronizeDemo1 {
	public synchronized static void fool1() throws Exception{
		System.out.println("fool1...开始");
		Thread.sleep(10000L);
		System.out.println("fool1...结束");
	}
	public synchronized static void fool2() throws Exception{
		System.out.println("fool2...开始");
		Thread.sleep(5000L);
		System.out.println("fool2...结束");
	}
	
	public static void main(String args[]){
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					SynchronizeDemo1.fool1();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					SynchronizeDemo1.fool2();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();;
	}
}

 

eg2、Synchronized加在成员方法上,不同的线程调用同一对象的成员方法互斥

package com.base.thread.synchronize;

public class SynchronizeDemo2 {
	public synchronized void fool1() throws Exception{
		System.out.println("fool1...开始");
		Thread.sleep(10000L);
		System.out.println("fool1...结束");
	}
	public synchronized void fool2() throws Exception{
		System.out.println("fool2...开始");
		Thread.sleep(5000L);
		System.out.println("fool2...结束");
	}
	
	public static void main(String args[]){
		final SynchronizeDemo2 synchronizeDemo2 = new SynchronizeDemo2();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
//					new SynchronizeDemo2().fool1();
					synchronizeDemo2.fool1();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
//					new SynchronizeDemo2().fool2();
					synchronizeDemo2.fool1();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();;
	}
}

eg3、foo3和foo4不互斥,foo1和foo4互斥,foo2和foo3互斥

 

public class SynchronizeDemo3 {
	public static synchronized void fool1() throws Exception{
		System.out.println("fool1...开始");
		Thread.sleep(10000L);
		System.out.println("fool1...结束");
	}
	public synchronized void fool2() throws Exception{
		System.out.println("fool2...开始");
		Thread.sleep(5000L);
		System.out.println("fool2...结束");
	}
	
	public void fool3() throws Exception{
		synchronized(this){
			System.out.println("fool3...开始");
			Thread.sleep(5000L);
			System.out.println("fool3...结束");
		}
	}
	public void fool4() throws Exception{
		synchronized(SynchronizeDemo3.class){
			System.out.println("fool4...开始");
			Thread.sleep(5000L);
			System.out.println("fool4...结束");
		}
	}
	public static void main(String args[]){
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					new SynchronizeDemo3().fool3();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					new SynchronizeDemo3().fool4();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}).start();;
	}
}

 

LOCK

Lock比synchronized更加面向对象,锁本身就是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象。

ReentrantLock

ReentrantLock是Lock的实现,被称作重入锁,它的功能比Synchronized强大,但是jdk1.6之后两者性能差别不大,Synchronized使用更简单清晰,所以多线程加锁还是首选Synchronized。

ReentrantLock提供了公平和非公平两种锁。通过构造方法可以实现,但是公平锁的性能远远低于非公平锁,因此非特殊情况优先非公平锁。

注意:ReenTrantLock使用之后,必须释放锁。

ReentrantLock 锁提供了如下重要的方法:

lock():获得锁,如果锁已经被占用,则等待

lockInterruptibly():获得锁,但优先响应中断

tryLock():尝试获得锁,如果成功,返回true,失败返回false。该方法不等待,立即返回

unlock():释放锁

ReentrantReadWriteLock 读写锁

分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。如果代码是只读数据,可以很多人同时读,但不能同时写,那就上读锁;如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上读锁,写的时候上写锁!

 

public class ReadWriteLockTest{
	private Integer num = 0;
	private Lock lock = new ReentrantLock();
	private ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
	private ReadLock readLock = reentrantReadWriteLock.readLock();
	private WriteLock writeLock = reentrantReadWriteLock.writeLock();

	public int read1(){
		try{
			lock.lock();
			Thread.sleep(10L);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
		return num;
	}
	public void write1(){
		try{
			lock.lock();
			num++;
		}finally{
			lock.unlock();
		}
	}
	
	public int read2(){
		try{
			readLock.lock();
			Thread.sleep(10L);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			readLock.unlock();
		}
		return num;
	}
	public void write2(){
		try{
			writeLock.lock();
			num++;
		}finally{
			writeLock.unlock();
		}
	}
	public Integer getNum() {
		return num;
	}
	public static void main(String args[]) throws Exception{
		long time1 = System.currentTimeMillis();
		final ReadWriteLockTest rwt = new ReadWriteLockTest();
		List<Thread> threadList = new ArrayList<>();
		for(int i = 0; i < 3000; i++){
			Thread t1 = new Thread(new Runnable() {
				@Override
				public void run() {
					rwt.write1();
//					rwt.write2();
				}
			});
			t1.start();
			Thread t2 = new Thread(new Runnable() {
				@Override
				public void run() {
					rwt.read1();
//					rwt.read2();
				}
			});
			t2.start();
			threadList.add(t1);
			threadList.add(t2);
		}
		
		for(Thread thread : threadList){
			thread.join();
		}
		System.out.println("num: " + rwt.getNum());
		System.out.println("耗时:" + (System.currentTimeMillis() - time1));
	} 
}

 

Condition

Condition可以替代传统的线程间通信,用await()替换wait(),用signal()替换notify(),用signalAll()替换notifyAll()。

——为什么方法名不直接叫wait()/notify()/nofityAll()?因为Object的这几个方法是final的,不可重写!

传统线程的通信方式,Condition都可以实现。

注意,Condition是被绑定到Lock上的,要创建一个Lock的Condition必须用newCondition()方法。

 

Condition的强大之处在于它可以为多个线程间建立不同的Condition

© 著作权归作者所有

共有 人打赏支持
EveryDayNew
粉丝 5
博文 45
码字总数 31409
作品 0
杭州
程序员
Intrinsic Locks and Synchronization

Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrin......

恋空御月
2016/08/19
5
0
Java 复习 —— 锁以及线程之间的通讯

1、Lock 1)1.5版本之后出现,java.util.concurrent.locks.Lock 2) Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的...

learn_more
2015/09/13
124
0
Locks in Java(翻译blog)

simple-lock from Java 5 the package java.util.concurrent.locks contains several lock implementations, so you may not have to implement your own locks. But you will still need to......

o0无忧亦无怖
2015/10/08
39
0
【19】Java中的Locks

原文地址:Locks in Java 作者: Jakob Jenkov --- Lock是一个类似同步代码块(synchronized block)的线程同步机制。同步代码块而言,Lock可以做到更细粒度的控制。 Lock(或者其他高级同步...

秋雨霏霏
2017/10/26
0
0
Synchronized和Lock的区别

1、Lock是java的一个interface接口,而synchronized是Java中的关键字,synchronized是由JDK实现的,不需要程序员编写代码去控制加锁和释放;Lock的接口如下: 2、synchronized修饰的代码在执...

zhglance
08/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【大福利】极客时间专栏返现二维码大汇总

我已经购买了如下专栏,大家通过我的二维码你可以获得一定额度的返现! 然后,再给大家来个福利,只要你通过我的二维码购买,并且关注了【飞鱼说编程】公众号,可以加我微信或者私聊我,我再...

飞鱼说编程
今天
1
0
Spring5对比Spring3.2源码之容器的基本实现

最近看了《Spring源码深度解析》,该书是基于Spring3.2版本的,其中关于第二章容器的基本实现部分,目前spring5的实现方式已有较大改变。 Spring3.2的实现: public void testSimpleLoad(){...

Ilike_Java
今天
1
0
【王阳明心学语录】-001

1.“破山中贼易,破心中贼难。” 2.“夫万事万物之理不外于吾心。” 3.“心即理也。”“心外无理,心外无物,心外无事。” 4.“人心之得其正者即道心;道心之失其正者即人心。” 5.“无...

卯金刀GG
今天
2
0
OSChina 周三乱弹 —— 我们无法成为野兽

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ _刚刚好: 霸王洗发水这波很骚 手机党少年们想听歌,请使劲儿戳(这里) hahahahahahh @嘻酱:居然忘了喝水。 让你喝可乐的话, 你准忘不了...

小小编辑
今天
11
0
vm GC 日志 配置及查看

-XX:+PrintGCDetails 打印 gc 日志 -XX:+PrintTenuringDistribution 监控晋升分布 -XX:+PrintGCTimeStamps 包含时间戳 -XX:+printGCDateStamps 包含时间 -Xloggc:<filename> 可以将数据保存为......

Canaan_
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部