- 锁是什么 ?
- 锁的什么?
- 怎么加锁 ?
- 什么时候加锁 ?
- 怎么实现高效率加锁 ?
锁是什么?
- java中的锁是一种线程同步机制,控制对共享资源的访问,来达到数据安全的一种工具。
- 本质是依赖于底层的操作系统的 Mutex Lock(互斥锁)来实现。
synchronized
通过
monitor对象监视器
来实现得,每个对象都有一个唯一得monitro- 1 ,加锁后,在代码编译后会生成
monitorenter
、
monitorexit
,在业务代码前后- 2 ,如果monitor 进入数为0,则进入monitor,持有 monitor,进入数设置为1,其它线程则阻塞,持由monitor得线程再进入,则进入数再+1
- 3 ,持有monitor得线程,执行monitorexit指令后,进入数-1,为0时推出monitor对象,不再拥有,其它线程可以尝试获取monitor持有权
怎么加锁 ?
synchronized
关键字、
Lock
锁
什么时候加锁 ?
- 线程是一个单独的资源类
- 多线程则是,多个线程 争抢同一共享资源
- 在资源竞争中,就会存在线程安全的问题,需要加锁控制
加锁线程排队-》基本表现
同步前-》
同步后-》
public class SaleTicketDemo {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(()->{
for (int i = 0; i < 30; i++) {
ticket.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 30; i++) {
ticket.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 30; i++) {
ticket.sale();
}
},"C").start();
}
}
//资源类
class Ticket{
private int number=30;
//synchronized 排队,锁 - 对象,class
public synchronized void sale(){
if (number>0){
System.out.println(Thread.currentThread().getName()+"卖出了"+number--+"票,剩余"+number);
}
}
}
锁的是什么?
- 普通同步方法,锁的是方法的调用者,对象的实例,该资源类对象
P p1 = new P(); P p2 = new P();
p1与p2 方法调用时,锁的就不一样。
public synchronized void m1(){}
- 静态同步方法,锁的是 资源类 对象.Class 类模板
public static synchronized void m1(){}
Lock 加锁
默认-
非公平锁
- 非公平: 不一定先排队得就先有机会加锁,而是出现各种线程随意抢占得情况
- 公平: 判断队列种是否有再排队得,如果有则按顺序排序,后来得进入队列尾部。
private Lock lock = new ReentrantLock();
public void m1(){
//加锁
lock.lock();
try {
//业务代码 ...
}catch (Exception e){
e.printStackTrace();
}finally {
//解锁
lock.unlock();
}
}
- Synchronized 适合少量代码同步,Lock适合锁大量的同步代码
- Synchronized 内置的java关键字,Lock是一个java 类
- Synchronized 无法判断获取锁的状态,Lock 可以判断是否获取到了锁
- Synchronized 会自动释放锁,lock 必须要手动释放锁! 如果不释放,可能出现死锁
- Synchronized 没有获取锁超时,会一直等待,Lock可以
- Synchronized 可重入锁,不可中断,非公平;Lock 可重入锁,可以判断锁,非公平(可设置)
线程执行顺序控制
- 1.Condition 精确控制通知唤醒
- 2.join() 方法线程插队
public class C {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.printB();
}
},"B").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.printC();
}
},"C").start();
}
}
class Data3{
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number = 1; // 1A 2B 3C
public void printA(){
lock.lock();
try {
//业务, 判断 -》 执行 -》通知
while (number!=1){
//等待
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"=>AAAAAAA");
//唤醒指定线程, B
//唤醒B
number =2;
condition2.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
while (number!=2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
number =3;
condition3.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
while (number!=3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"=>CCCCCCCCC");
number =1;
condition1.signal();
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
Thread thread = new Thread(threadOrder::methodA1);
thread.start();
thread.join();
Thread thread1 = new Thread(threadOrder::methodB1);
thread1.start();
thread1.join();
线程近乎同时执行
CountDownLatch
、
CyclicBarrier
- 并行流
.parallelStream()
public class CountDownLatchTest implements Runnable{
private CountDownLatch countDownLatch;
public CountDownLatchTest(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
try {
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName() + "启动" + System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int count = Runtime.getRuntime().availableProcessors();
CountDownLatch latch = new CountDownLatch(count);
for (int i = 0; i < count ; i++) {
new Thread(new CountDownLatchTest(latch)).start();
}
}
}
public class CountDownLatchTest implements Runnable{
private CyclicBarrier cyclicBarrier;
public CountDownLatchTest(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + "启动" + System.currentTimeMillis());
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int count = Runtime.getRuntime().availableProcessors();
CyclicBarrier cyclicBarrier = new CyclicBarrier(count);
for (int i = 0; i < count; i++) {
new Thread(new CountDownLatchTest(cyclicBarrier)).start();
}
}
}
public static void main(String[] args) {
List<Runnable> threads = new ArrayList<>();
for (int i = 0; i < 50; i++) {
int finalI = i;
threads.add(new Thread(()->{System.out.println("线程"+ finalI +"执行: "+ LocalDateTime.now());}));
}
threads.parallelStream().forEach(e->{
new Thread(e).start();
});
}
版权声明:本文为hesqlplus730原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。