Synchronized锁的缺陷
Synchronized不会手动释放锁资源,当线程发生阻塞后,其他线程只能眼睁睁的等着,不会分别是读线程和写线程,读问题并不会引发高并发,但是synchronized锁不能识别是读线程还是锁线程 ,遇到了都会锁上。另外没有中断锁的功能,一个线路等待时间过长不会自我中断线程。
Lock锁
一、概述
1.Lock是JDK1.5中提供的一套用于取代synchronized的机制
2.相对synchronized而言,Lock更加灵活和精细 - synchronized在使用的时候需要确定锁对象,如果确定错误或者锁形成嵌套,容易出现死锁;Lock由程序员自己创建,在使用的时候无需找锁对象而是直接调用方法加锁解锁即可
1.ReentrantLock - 重入锁:允许锁资源被同一个线程多次占用,也允许这个锁资源被不同的线程占用
2.锁的公平和非公平策略:
1.在资源有限的情况下,线程之间实际抢占执行到的次数不一定均等,这种现象称之为非公平策略
2.公平策略在使用的时候需要定义队列,而线程并不是直接抢占资源而是抢占入队顺序,这种情况下每一个线程的执行次数是大致相等
3.相对非公平策略而言,公平策略需要耗费更多的内存,需要涉及到线程调度,所以公平策略的效率相对较低
4.Lock和synchronized默认是非公平策略
·公平锁: ReentrantLock pairLock =new eentrantLock(true)--相当于,线程需要进入队列中等待,调用使用完后又进入队咧最后,重新等待。先进先出。
·非公平锁: ReentrantLock pairLock =new ReentrantLock(false 构造函 数不传
数,则默认是非公平锁
二 其他
1.CountDownLatch:闭锁/线程递减锁。会对线程进行计数,在计数归零之前会进行阻塞,直到计数归零才会放开阻塞 - 一组线程结束之后开启另一组线程
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {CountDownLatch cdl = new CountDownLatch(7);new Thread(new Teacher(cdl)).start();new Thread(new Teacher(cdl)).start();new Thread(new Student(cdl)).start();new Thread(new Student(cdl)).start();new Thread(new Student(cdl)).start();new Thread(new Student(cdl)).start();new Thread(new Student(cdl)).start();// 正常情况下:应该是考官和考生都到达考场之后才能开始考试// 在上面七个线程执行完成之前,主线程应该陷入阻塞// 在计数归零之前,需要阻塞cdl.await();System.out.println("开始考试");}
}
class Teacher implements Runnable {
private CountDownLatch cdl;public Teacher(CountDownLatch cdl) {this.cdl = cdl;
}@Override
public void run() {try {// 模拟考官到考场的时间Thread.sleep((long) (Math.random() * 10000));System.out.println("考官到达考场");// 减少一个计数cdl.countDown();} catch (InterruptedException e) {e.printStackTrace();}
}
}
class Student implements Runnable {
private CountDownLatch cdl;public Student(CountDownLatch cdl) {this.cdl = cdl;
}@Override
public void run() {try {// 模拟考生到达考场的时间Thread.sleep((long) (Math.random() * 10000));System.out.println("考生到达考场");cdl.countDown();} catch (InterruptedException e) {e.printStackTrace();}
}
}
1.CyclicBarrier:栅栏。会对线程进行计数,在计数归零之前会进行阻塞,直到计数归零才会放开阻塞 - 这一组线程到达同一个点之后在分别继续往下执行
/*
举例:跑步比赛
所有的运动员都到了起跑线之后,才能往外跑
*/
public class CyclicBarrierDemo {
public static void main(String[] args) {CyclicBarrier cb = new CyclicBarrier(6);new Thread(new Runner(cb), "1号").start();new Thread(new Runner(cb), "2号").start();new Thread(new Runner(cb), "3号").start();new Thread(new Runner(cb), "4号").start();new Thread(new Runner(cb), "5号").start();new Thread(new Runner(cb), "6号").start();}
}
fdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxfdxxxxxxxxxxxxxxxxxxffxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx// 运动员
class Runner implements Runnable {
private CyclicBarrier cb;public Runner(CyclicBarrier cb) {this.cb = cb;
}@Override
public void run() {try {// 模拟每一个人到起跑线的时间Thread.sleep((long) (Math.random() * 10000));String name = Thread.currentThread().getName();System.out.println(name + "运动员到了起跑线");// 正常情况下:应该是所有的运动员都到了起跑线之后才能往外跑// 也就意味着先到的运动员应该在这儿等待,等大家到齐再往外跑// 在阻塞的时候同时减少计数,当计数归零之后放开阻塞cb.await();System.out.println(name + "运动员跑了出去");} catch (Exception e) {e.printStackTrace();}}
}
、、