Java8——线程的同步与死锁

同步问题的引出:

范例:卖票问题

class MyThread implements Runnable {
	private int ticket = 5;

	@Override
	public void run() {
		for (int x = 0; x < 20; x++) {
			if (ticket > 0) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "卖票, 卖出的票数为" + ticket--);
			}

		}
	}
}

public class test {
	public static void main(String args[]) throws Exception {
		MyThread mt = new MyThread();
		new Thread(mt, "票贩子A").start();
		new Thread(mt, "票贩子B").start();
		new Thread(mt, "票贩子C").start();
		new Thread(mt, "票贩子D").start();
	}
}

解释:当系统只剩下一张票的时候,票贩子A检测到还剩余一张票随后进入到sleep状态,票贩子B、C、D均是如此,当大家都认为还剩一张票的时候,票贩子A 取走了这张票,ticket执行减减操作;此时剩余票数为0,这时会出现安全问题;

同步处理:

出现上述问题的原因是:判断和执行的操作是分开进行的;

解决办法:将判断剩余票数和票数减一的操作封装起来,是一起执行的,当一个线程在执行操作的时候,其他的线程将会等待;

在Java中如果想实现同步需要使用synchronized关键字 。而这个关键字可以通过2种方式使用:

  • 同步代码块;
  • 同步方法;

范例:观察同步块

同步块必须要锁一个对象,往往会锁住当前对象;

class MyThread implements Runnable {
	private int ticket = 5;

	@Override
	public void run() {
		for (int x = 0; x < 20; x++) {
			synchronized(this){	//当前对象每次只允许一个对象进入
				if (ticket > 0) {
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.println(Thread.currentThread().getName() + "卖票, 卖出的票数为" + ticket--);
				}
			}
		}
	}
}

public class test {
	public static void main(String args[]) throws Exception {
		MyThread mt = new MyThread();
		new Thread(mt, "票贩子A").start();
		new Thread(mt, "票贩子B").start();
		new Thread(mt, "票贩子C").start();
		new Thread(mt, "票贩子D").start();
	}
}

范例:同步方法解决

class MyThread implements Runnable {
	private int ticket = 5;

	@Override
	public void run() {
		for (int x = 0; x < 20; x++) {
			this.scale();
		}
	}
	public synchronized void scale(){	//同步方法
		if (ticket > 0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "卖票, 卖出的票数为" + ticket--);
		}
	}
}

public class test {
	public static void main(String args[]) throws Exception {
		MyThread mt = new MyThread();
		new Thread(mt, "票贩子A").start();
		new Thread(mt, "票贩子B").start();
		new Thread(mt, "票贩子C").start();
		new Thread(mt, "票贩子D").start();
	}
}

多个线程访问同一资源的时候需要同步操作;同步操作与异步操作比,异步操作比同步操作的速度更快,但是同步操作安全性更高,属于安全的线程操作;

死锁:

同步过多可能会产生死锁;比如本和笔的故事;

面试题:请解释多个资源访问同一资源时需要考虑哪些情况?可能会带来哪些问题?

  • 多个线程访问同一资源时要处理好同步关系,可以使用同步代码块或者同步方法完成;

       |- 同步代码块: synchronized (锁定对象){代码}

       |- 同步方法:public synchronized 返回值 方法名称(){代码}

  • 过多使用同步可能会造成死锁;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值