文档章节

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
JAVA Synchronized 与 Lock接口的区别

synchronized 关于synchronized字段,不管该关键字是修饰方法还是修饰同步代码块,synchronzed拿到的都是对象。 当synchronized修饰的是方法时,synchronized所拿到的是调用该方法的对象的锁...

kdy1994
08/09
0
0
【19】Java中的Locks

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

秋雨霏霏
2017/10/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Eos如何删除钱包

在使用Eos的keosd钱包软件时,如果要删除EOS中指定名称的钱包,最简单的办法是直接删除钱包文件,不过在删除钱包之前,需要先停止钱包软件的运行。 学习EOS应用开发要选这个:【EOS智能合约与...

geek12345
4分钟前
0
0
js操作时间

获取当前时间 function getSystemDate(){ var systemDate = new Date(); // 获取当年 var year = systemDate.getFullYear(); // 获取当月 (月+1是因为js中......

简心
11分钟前
0
0
区块链开发教程推荐

区块链的重要性已经毋庸置疑,但对大多数跃跃欲试的开发者而言,去中心化思想、非对称加密、共识算法等技术点的理解和运用,都是入门区块链开发的挑战。合适的区块链开发教程可以极大地缩短区...

笔阁
11分钟前
0
0
菜单menuView总结

1、FTPopOverMenu

_____1____
22分钟前
2
0
MyEclipse教程:Web开发——部署和测试Web项目

MyEclipse 在线订购年终抄底促销!火爆开抢>> MyEclipse最新版下载 本教程向用户展示了使用关联的Web项目创建Web片段项目的机制。用户还可以获得要检查的示例项目。在本教程中,用户将学习如...

电池盒
38分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部