Java中线程同步和线程死锁问题

时间:2021-07-04 18:32:51

在这里我总结两方面的内容:线程同步与线程死锁,两者之间也存在一定关系,也正是因为线程同步才会处出现线程死锁的问题,现在首先来看线程同步的内容。

线程同步是这样一类问题:当一个有限的资源被多个线程共享的时候,为了保证对共享资源的互斥访问,我们一定要给他们排出一个先来后到。而要做到这一点,对象锁在这里起着非常重要的作用。每一个对象都有一把锁,而且只有一把锁,一个线程拿到之后别的对象便拿不到这个锁了,只能等那个线程执行完之后释放对象锁,别的线程才可以拿到锁执行后续操作,这样一来也就有了原子操作的概念,所谓原子操作就是那些不能被打断的操作,而加锁的过程就要用到 Synchronized,同步机制是通过对象锁来实现的,实现线程同步有以下几个方法和需要注意的地方:

同步方法有两种,可以同步方法,也可以同步语句块,同步方法就像平常的类修饰关键字一样,代码如下:

public synchronized void move(){

               //要同步的语句......

        }

也可以通过同步语句块的方式来实现,代码如下:

        synchronized(obj){

               //要同步的代码……

}

同步语句块里的obj是一个要同步的对象,那在同步的时候要注意的是同步必须是同步同一个对象,我们来看下面的例子:

public class Test {
/**
*
*/
public static void main(String[] args){
MyThread t1 = new MyThread("t1");
MyThread t2 = new MyThread("t2");
MyThread t3 = new MyThread("t3");
t1.start();
t2.start();
t3.start();

}
public static class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name = name;
}
public void run(){
for(int i=0;i<100;i++){
System.out.println("这是"+name+"的"+"第"+i+"个数");
}
}
};
}

这段代码我希望的结果是想让三个线程对象分别数数,从1到100,但是要一个数完之后另一个再开始数,但是现在的输出结果却是这样子的: Java中线程同步和线程死锁问题

我们可以看到,虽然每个线程对象内部是有序输出的,比如t1的顺序是从0到99,但是整体并不是t1完了之后再执行其他线程,我们想要的t1数数是一个原子操作,就是不能有其他的线程穿插进来,但是现在并不是这样子的效果,于是,我们改进为以下的代码:

public class Test {
/**
*
*/

public static void main(String[] args){
Object obj = "string";
MyThread t1 = new MyThread("t1",obj);
MyThread t2 = new MyThread("t2",obj);
MyThread t3 = new MyThread("t3",obj);

t1.start();
t2.start();
t3.start();

}
public static class MyThread extends Thread{
private String name;
private Object obj;
public MyThread(String name,Object obj){
this.name = name;
this.obj = obj;
}
public void run(){
synchronized (obj) {
for(int i=0;i<100;i++){
System.out.println("这是"+name+"的"+"第"+i+"个数");
}
}

}
};
}

这样子之后的输出效果是这样子的: Java中线程同步和线程死锁问题

这个我们可以很明显得看到达到了我们想要的效果,在这段代码里做的改动就是在mian里面声明了一个对象,然后作为共享的对象传入线程里,三个线程在执行的时候由于拿到的是同一个对象,这个对象就好比是共享的资料一样,这个对象只有一把锁,在系统调度t1线程进入run之后拿到了对象的锁,之后就必须让for执行完,之后释放锁,别的线程才可以拿到,这样就让每个线程变成了一个原子操作,在写的时候很可能会犯这样的错误,请看代码:

public class Test {
/**
*
*/

public static void main(String[] args){
Object obj = "string";
MyThread t1 = new MyThread("t1",obj);
MyThread t2 = new MyThread("t2",obj);
MyThread t3 = new MyThread("t3",obj);
synchronized (obj) {
t1.start();
}
synchronized (obj) {
t2.start();
}
synchronized (obj) {
t3.start();
}



}
public static class MyThread extends Thread{
private String name;
private Object obj;
public MyThread(String name,Object obj){
this.name = name;
this.obj = obj;
}
public void run(){

for(int i=0;i<100;i++){
System.out.println("这是"+name+"的"+"第"+i+"个数");
}
}


};
}

这样子的运行效果和第一种类似,先写到这里