java复习-线程的同步和死锁

本文介绍了Java中线程同步的问题,包括同步代码块和同步方法的使用,以及如何避免因不当同步导致的死锁。通过票贩子买票的例子详细展示了同步机制的应用及性能影响。
摘要由CSDN通过智能技术生成

线程的同步和死锁

同步问题引出

当多个线程访问同一资源时,会出现不同步问题。比如当票贩子A(线程A)已经通过了“判断”,但由于网络延迟,暂未修改票数的间隔时间内,票贩子B(线程B)也通过了“判断”。此时,若票数只剩下了最后一张,则会出现两个线程同时通过判断并最终会修改票数,出现错误(票数为0或-1)。
在这里插入图片描述

线程同步处理

解决同步问题的关键是锁,指的是当某一个线程执行操作的时候,其它线程外面等待。
在这里插入图片描述

现这把锁的功能,就可以使用 synchronized 关键字来实现,利用此关键字可以定义同步方法或同步代码块, 在同步代码块的操作里面的代码只允许一个线程执行。

1. 同步代码块

synchronized(同步对象){
    同步代码操作;
}

一般要进行同步对象处理的时候可以采用当前对象 this 进行同步。
卖票范例(同步代码块版):

class MyThread implements Runnable { // 线程的主体类
	private int ticket = 5;

	@Override
	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() + "买票,ticket = " + this.ticket --);				
				} else { 
					System.out.println("-----票已售完-----");
					break;
				}
			}
		}
	}
}
public class ThreadDemo {
	public static void main(String[] args) {
		MyThread mt = new MyThread();
		new Thread(mt,"票贩子A").start(); 
		new Thread(mt,"票贩子B").start(); 
		new Thread(mt,"票贩子C").start(); 
		
	}
}

结果:

票贩子A买票,ticket = 5
票贩子C买票,ticket = 4
票贩子C买票,ticket = 3
票贩子C买票,ticket = 2
票贩子B买票,ticket = 1
-----票已售完-----
-----票已售完-----
-----票已售完-----

加入同步处理之后,程序的整体的性能下降了。同步实际上会造成性能的降低。

2. 同步方法

只需要在方法定义上使用synchronized 关键字即可。

class MyThread implements Runnable { // 线程的主体类
	private int ticket = 5;

	public synchronized boolean sale() { // 每一次只允许一个线程进行访问该方法
		if (this.ticket > 0) {
			try {
				Thread.sleep(100);  // 模拟网络延迟
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "买票,ticket = " + this.ticket --);
			return true;
		} else { 
			System.out.println("-----票已售完-----");
			return false;
		}
	}
	
	@Override
	public void run() {
		while(this.sale()) {}
	}
}
public class ThreadDemo {
	public static void main(String[] args) {
		MyThread mt = new MyThread();
		new Thread(mt,"票贩子A").start(); 
		new Thread(mt,"票贩子B").start(); 
		new Thread(mt,"票贩子C").start(); 
		
	}
}

结果:

票贩子A买票,ticket = 5
票贩子A买票,ticket = 4
票贩子A买票,ticket = 3
票贩子C买票,ticket = 2
票贩子C买票,ticket = 1
-----票已售完-----
-----票已售完-----
-----票已售完-----

在日后学习 Java 类库的时候会发现,系统中许多的类上使用的同步处理采用的都是同步方法。

线程死锁

死锁是在进行多线程同步的处理之中有可能产生的一种问题,所谓的死锁指的是若干个线程彼此互相等待的状态。
若干个线程访问同一资源时一定要进行同步处理,而过多的同步会造成死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值