Synchronized是并发中使用最频繁的关键字了,它可使用在方法、代码块上,表示对该段代码加锁,而必需要持有锁才能执行这段代码。Synchronized具备互斥性。java
提及来蛮简单,而实际中编程 ,最可贵地方有两点编程
一、肯定并发间隙多线程
二、肯定锁的对象并发
作好这两点才能处理好锁的粒度,是并发的性能更好。ide
eg一、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();; } }
eg二、Synchronized加在成员方法上,不一样的线程调用同一对象的成员方法互斥this
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();; } }
eg三、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();; } }
LOCKcode
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