Java多线程:线程的同步与死锁

在多线程的处理之中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,于是当多个线程访问同一资源的时候,如果处理不当就会产生数据的错误操作。

同步问题的引出

范例:创建若干个线程对象实现卖票操作

class MyThread implements Runnable{
	private int ticket = 10;
	
	public void run() {
		while(true) {
			if(this.ticket > 0) {
				try {
					Thread.sleep(100);	// 模拟网络延迟操作
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + " " + this.ticket--);
			}
			else {
				System.out.println("无票");
				break;
			}
		}
	}
}
public class Main{
	
	public static void main(String args[]) throws Exception {
		MyThread mt = new MyThread();
		new Thread(mt, "窗口1").start();
		new Thread(mt, "窗口2").start();
		new Thread(mt, "窗口3").start();
		
		
	}
}

当有延迟的时候就能很轻易地看到问题所在

解决同步问题的关键是锁,指的是当某一个线程执行操作的时候,其他线程外面等待。

使用synchronized关键字可以定义同步方法或者同步代码块;在同步代码块的操作里面的代码同一时间只允许一个线程执行。

1.利用同步代码块进行处理

synchronized(同步对象){

同步代码操作;

}

一般要进行同步对象处理的时候可以采用当前对象this进行同步。

范例:利用同步代码块解决数据同步访问问题

class MyThread implements Runnable{
	private int ticket = 10;
	
	public void run() {
		while(true) {
			synchronized(this) {	// 同步代码块
				if(this.ticket > 0) {
					try {
						Thread.sleep(100);	// 模拟网络延迟操作
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + " " + this.ticket--);
				}
				else {
					System.out.println("无票");
					break;
				}
			}
		}
	}
}
public class Main{
	
	public static void main(String args[]) throws Exception {
		MyThread mt = new MyThread();
		new Thread(mt, "窗口1").start();
		new Thread(mt, "窗口2").start();
		new Thread(mt, "窗口3").start();
	}
}

加入同步之后,虽然不会再出现数据上出错的问题,但是程序的整体行能下降了。

2.利用同步方法解决:只需要再方法定义上使用synchronized关键字即可

class MyThread implements Runnable{
	private int ticket = 10;
	
	public synchronized boolean sale() {
		if(this.ticket > 0) {
			try {
				Thread.sleep(100);	// 模拟网络延迟操作
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + " " + this.ticket--);
			return true;
		}
		else {
			System.out.println("无票");
			return false;
		}
	}
	@Override
	public void run() {
		while(true) {
			if(!this.sale()) {
				break;
			}
		}
	}
}
public class Main{
	
	public static void main(String args[]) throws Exception {
		MyThread mt = new MyThread();
		new Thread(mt, "窗口1").start();
		new Thread(mt, "窗口2").start();
		new Thread(mt, "窗口3").start();
	}
}

使用同步代码块和同步方法并没有多大差别,但是再Java类库许多类上的同步处理都是用的是同步方法。

死锁

死锁是再进行多线程同步处理中有可能出现的问题。所谓的死锁指的是若干个线程彼此互相等待的状态。

范例:

package threads;

class test1{
	public synchronized void func(test2 t2) {
		System.out.println("我是test1,需要一个test2的对象");
		t2.get();
	}
	public synchronized void get() {
		System.out.println("我是test1,得到了一个test2的对象");
	}
}

class test2{
	public synchronized void func(test1 t1) {
		System.out.println("我是test2, 需要一个test1的对象");
		t1.get();
	}
	public synchronized void get() {
		System.out.println("我是test2,得到了一个test1的对象");
	}
}

public class DeadLock implements Runnable{
	private test1 t1 = new test1();
	private test2 t2 = new test2();
	public DeadLock() {
		new Thread(this).start();	// 新启动一个线程
		t2.func(t1);
	}
	@Override
	public void run() {
		t1.func(t2);
	}

	public static void main(String[] args) {
		new DeadLock();
		
	}

}

造成死锁的原因是互相等待。

若干个线程访问同一资源时一定要进行同步处理,而过多的同步处理会造成死锁。

死锁是同步引起的。

发布了238 篇原创文章 · 获赞 104 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/hpu2022/article/details/103338381