Java的锁和多线程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_19107011/article/details/97296264

Thread的几种状态

定义在 java.lang.Thread.State 里面 状态分别是:
NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING 、TERMINATED

BLOCKED 和 WAITING的区别

在这里插入图片描述
堵塞状态:
一个线程因为等待临界区的锁被阻塞产生的状态
Lock 或者synchronize 关键字产生的状态
等待状态:
一个线程进入了锁,但是需要等待其他线程执行某些操作。时间确定
通过sleep或wait timeout方法进入的限期等待的状态)

同步锁

参考:https://www.cnblogs.com/ygj0930/p/6561667.html

一:Monitor

      Monitor是一个同步工具,相当于操作系统中的互斥量(mutex),即值为1的信号量。

      它内置与每一个Object对象中,相当于一个许可证。拿到许可证即可以进行操作,没有拿到则需要阻塞等待。

 

    二:syncrhoized实现原理

       syncrhoized又叫做内置锁,为什么呢?因为使用syncrhoized加锁的同步代码块在字节码引擎中执行时,其实是通过锁对象的monitor的取用与释放来实现的。由上面我们直到Monitor是内置于任何一个对象中的,syncrhoized利用monitor来实现加锁解锁,故syncrhoized又叫做内置锁。

       现在我们知道为什么用syncrhoized(lock)来加锁时,锁对象可以是任意对象了:

       1:syncrhoized(lock)加锁时,用到的其实只是lock对象内置的monitor而已;

       2:一个对象的monitor是唯一的,相当于一个唯一的许可证。拿到许可证的线程才可以执行,执行完后释放对象的monitor才可以被其他线程获取。

 

       我们来讲解一下syncrhoized加锁的同步块的执行过程:

       现在假设有代码块:  syncrhoized(Object lock){

                                                                         同步代码...;

                                    }

 

        它在字节码文件中被编译为:monitorenter;//获取monitor许可证,进入同步块

                                             同步代码...

                                             monitorexit;//离开同步块后,释放monitor许可证

                         

条件对象

条件对象是用在这种场景下,比如一个条件获得锁,可是它执行的条件不满足
需要等待,此时可以使用条件对象。
条件对象主要有三个方法
await、notify、notifyAll
最好使用notifyAll,因为notify唤醒的是随机的,如果线程不满足,就继续等待啦,如果没有其他线程唤醒,就死锁啦。
nofigy效率高,nogifyAll效率低。
使用可以参考https://www.jianshu.com/p/25e243850bd2?appinstall=0

账户1余额:200

账户2余额:300

线程1:账户1→账户2300)

线程2:账户2→账户1400)
因为线程1和线程2的金额都不足以进行转账,所以两个线程都阻塞了,这种状态就叫死锁(deadlock),如果所有线程死锁,程序就卡死了。

线程可见

使用volatile和final

安全的线程集合

ConcurrentHashMap、CopyOnWriteArrayList

线程池

所有实现了ExecutorService接口(Executor的子接口)的实现类都是线程池,可以分为三大类

ForkJoinPool
ScheduledThreadPoolExecutor
ThreadPoolExecutor

具体的线程池,在工具类Executors中预创建了六小类

实现了ThreadPoolExecutor类:

ExecutorService newCachedThreadPool():无界线程池
ExecutorService newFixedThreadPool():有界线程池
ExecutorService newSingleThreadExecutor():单一线程池
实现了ScheduledThreadPoolExecutor类:

ScheduledExecutorService newSingleThreadScheduledExecutor()
ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
实现了ForkJoinPool类:
ExecutorService newWorkStealingPool()

参数

int corePoolSize:核心线程数,即使空闲也仍保留在池中的线程数
int maximumPoolSize:最大线程数
BlockingQueue workQueue:阻塞队列,在执行任务之前用于保存任务的队列
long keepAliveTime:保持激活时间,当线程数大于核心数时,这是多余的空闲线程在终止之前等待新任务的最大时间

参考

https://jodjod.blog.csdn.net/article/details/88749564#线程池的分类

猜你喜欢

转载自blog.csdn.net/qq_19107011/article/details/97296264