文档章节

Synchronized与Lock

潜化
 潜化
发布于 2016/10/02 23:54
字数 1078
阅读 125
收藏 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

© 著作权归作者所有

潜化
粉丝 6
博文 46
码字总数 31901
作品 0
长宁
程序员
私信 提问
加载中

评论(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
11
0
Java自学-多线程 Lock对象

多线程 Lock对象 与synchronized类似的,lock也能够达到同步的效果 步骤 1 : 回忆 synchronized 同步的方式 首先回忆一下 synchronized 同步对象的方式 当一个线程占用 synchronized 同步对象...

osc_9yc7q9oq
03/06
2
0
lock与synchronized的区别

1.  Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现,synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执...

osc_in99ca4i
04/16
2
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
43
0
synchronized 和 java.util.concurrent.locks.Lock 的异同 ?

主要相同点:Lock 能完成 synchronized 所实现的所有功能主要不同点:Lock 有比synchronized 更精确的线程语义和更好的性能。synchronized 会自动释放锁,而 Lock 一定要求程序员手工释放,并...

osc_7ei0ce8w
02/06
2
0

没有更多内容

加载失败,请刷新页面

加载更多

给大家讲一个笑话:技术是无国界的!

在我接触互联网的最初几年,总会在技术论坛上看到有人宣称:技术是没有国界的,我深信不疑! 做程序员之后,我慢慢接触到了很多很多的开源软件,我真的无比的感慨:开源是人类最伟大的发明。...

osc_hzf6peqc
1分钟前
0
0
医学多模态图像分割小结 - 知乎

在医学图象中,多模态数据因成像机理不同而能从多种层面提供信息。多模态图像分割包含重点问题为如何融合(fusion)不同模态间信息,本文主要记录笔者最近所读,欢迎批评指正补充 1. A review:...

osc_htns3spg
2分钟前
0
0
Curve-GCN:图卷积网络用于活动轮廓演变 - 知乎

CNN做分割需要处理数据量很大的grid数据,需要对所有点的label进行预测,而且传统CNN并不会结合点与点之间的联系。 使用图结构建模分割轮廓或分割曲面,然后采用GCN,仿照传统的deformable ...

osc_q7wo0k6s
3分钟前
0
0
录好的音频在哪个文件夹?迅捷录音软件还能这么查找!

录好的音频在哪个文件夹?在录制之前经常忘记调整保存位置,等到录完音频才发现,自己竟然找不到音频文件了。这种情况在录音的时候并不少见,软件的音频文件会默认保存在安装目录下,找起来确...

dawda
4分钟前
9
0
docker: Error response from daemon: Conflict. The container name "/xx" is already in use

使用docker 出现Error response from daemon: Conflict. The container name “***” is already in use 解决方法: (1)给容器换一个名字, 比如说 docker run -it --name=mycentos2 centos......

osc_h7q38oso
4分钟前
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部