java线程
死锁
在java中使用多线程 ,有可能导致死锁问题,死锁问题的出现会导致对应线程卡住,程序不再往下执行
死锁产生的原因:
- 当前线程拥有其他线程需要的资源
- 当前线程等待其他线程已拥有的资源
- 都不放弃自己拥有的资源
死锁实现
锁顺序产生死锁
class Test{
Object o1 = new Object();
Object o2 = new Object();
public void one(){
synchronized(o1){
//交替使用锁
synchronized(o2){
某个方法();
}
}
}
public void two(){
synchronized(o2){
//交替使用锁
synchronized(o1){
某个方法();
}
}
}
}
实际可能出现的状况:
线程A执行--》调用one()--》获得o1锁--》准备获得o2锁
线程B同时执行--》调用two()--》获得o2锁-》准备获得o1锁
此时,A需要等待B释放o2锁,才能继续执行,同理B需要等待A释放o1锁。
所以参生了死锁
协作对象发生死锁
public static void main(String[] args) {
Police p = new Police();
Culprit c = new Culprit();
new Thread(new MyRunnable(c,p)).start();
c.say(p);
}
static class MyRunnable implements Runnable{
private Culprit c;
private Police p ;
public MyRunnable(Culprit c, Police p) {
this.c = c;
this.p = p;
}
@Override
public void run() {
// TODO Auto-generated method stub
p.say(c);
}
}
static class Police{
public synchronized void say(Culprit c) {
System.out.println("警察:你放了人质你就可以走");
c.run();
}
public synchronized void fun() {
System.out.println("警察救了人质,但是罪犯跑了");
}
}
static class Culprit{
public synchronized void say(Police p) {
System.out.println("罪犯:你放了我。人质就可以走");
p.fun();
}
public synchronized void run() {
System.out.println("罪犯跑了,然后罪犯放了人质");
}
}
运行结果:
罪犯:你放了我。人质就可以走
警察:你放了人质你就可以走
避免死锁
- 固定加锁的顺序(针对锁顺序死锁)
- 开放调用(针对对象之间协作造成的死锁)
-
使用定时锁-->
tryLock()
- 如果等待获取锁时间超时,则抛出异常而不是一直等待!
如果所有线程以固定的顺序来获得锁,那么程序中就不会出现锁顺序死锁问题
class Test{
Object o1 = new Object();
Object o2 = new Object();
public void one(){
synchronized(o1){
//固定顺序锁
synchronized(o2){
某个方法();
}
}
}
public void two(){
synchronized(o1){
//固定顺序使用锁
synchronized(o2){
某个方法();
}
}
}
}
//可以使用根据hash值上锁
使用定时锁
使用显式Lock锁,在获取锁时使用tryLock()方法。当等待超过时限的时候,tryLock()不会一直等待,而是返回错误信息。
开放调用
如果在调用某个方法时不需要持有锁,那么这种调用被称为开放调用
简单的说就是使用同步代码块仅被用于保护那些涉及共享状态的操作
public static void main(String[] args) {
Police p = new Police();
Culprit c = new Culprit();
new Thread(new MyRunnable(c,p)).start();
c.say(p);
}
static class MyRunnable implements Runnable{
private Culprit c;
private Police p ;
public MyRunnable(Culprit c, Police p) {
this.c = c;
this.p = p;
}
@Override
public void run() {
// TODO Auto-generated method stub
p.say(c);
}
}
static class Police{
public synchronized void say(Culprit c) {
synchronized(this) {
System.out.println("警察:你放了人质你就可以走");
c.run();
}
}
public synchronized void fun() {
System.out.println("警察救了人质,但是罪犯跑了");
}
}
static class Culprit{
public synchronized void say(Police p) {
synchronized(this) {
System.out.println("罪犯:你放了我。人质就可以走");
p.fun();
}
}
public synchronized void run() {
System.out.println("罪犯跑了,然后罪犯放了人质");
}
}
结果:
罪犯:你放了我。人质就可以走
警察救了人质,但是罪犯跑了
警察:你放了人质你就可以走
罪犯跑了,然后罪犯放了人质