synchronized实现同步的基础:Java中的每一个对象都可以作为锁,3中形式
- 对于普通同步方法,锁时当前实例对象
- 对于静态同步方法,锁是当前类的Class对象
对于同步方法块,锁是Synchronized括号里配置的对象
1、公平锁与非公平锁
private Lock lock=new ReentrantLock();//无参构造,默认为false,非公平锁
相当于private Lock lock=new ReentrantLock(false)
- private Lock lock=new ReentrantLock(true);//有参构造,值为true,公平锁
非公平锁:饿死线程,但是效率相对较高
公平锁:阳光普照,效率相对较低
2、可重入锁
2.1、Synchronized实现可重入锁
代码演示:由于最外层,中层和内层用的是同一把锁,所以代码均会被执行。
输出结果:
- 最外层
- 中层
内存
public class Demo {
public static void main(String[] args) {
Demo demo = new Demo();
new Thread(()->{
synchronized (demo){
System.out.println("最外层");
synchronized (demo){
System.out.println("中层");
synchronized (demo){
System.out.println("内层");
}
}
}
}).start();
}
}
由于同步方法上的锁为当前实例对象,所以会不断递归调用,直至栈溢出
public class Demo {
public synchronized void add(){
add();
}
public static void main(String[] args) {
Demo demo = new Demo();
new Thread(()->{
demo.add;
}).start();
}
}
2.2、Lock实现可重入锁
注意:上锁与解锁缺一不可,否则其他线程在获取锁的时候,得不到锁会出现死锁的情况。 ```java public class Demo { public static void main(String[] args) {
Lock lock=new ReentrantLock();
new Thread(()->{
try{
lock.lock();
System.out.println(Thread.currentThread().getName()+"最外层");
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"内层");
}finally {
lock.unlock();
}
}finally {
lock.unlock();
}
},"t1").start();
} }
<a name="NOw0W"></a>
## 3、死锁
- 什么是死锁?
两个或者两个以上的进程在执行过程中,因为争夺资源而造成一种互相等待的现象,如果没有外力干涉,他们无法再执行下去。
- 产生死锁的原因
-系统资源不足<br />-进程运行推进顺序不合适<br />-资源分配不当
- 死锁演示-为了增减概率sleep
```java
public class DeadLockDemo {
static Object a = new Object();
static Object b = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (a) {
System.out.println(Thread.currentThread().getName() + "拥有锁a,等待获取锁b");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b) {
System.out.println(Thread.currentThread().getName() + "拥有锁b,等待获取锁a");
}
}
},"A").start();
new Thread(() -> {
synchronized (b) {
System.out.println(Thread.currentThread().getName() + "拥有锁b,等待获取锁a");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a) {
System.out.println(Thread.currentThread().getName() + "拥有锁a,等待获取锁b");
}
}
},"B").start();
}
}
- 验证死锁
1、jps 类似于Linux ps -ef,在jdk的bin安装目录下,环境变量必须配置
2、jstack jvm自带的堆栈跟踪工具
1、演示
第一步 jps -l
第二步 jstack 端口号 此时便会提示是否有死锁