线程的同步

首先想到线程同步就会想到线程异步

  • 所谓同步:就是一段时间内只做一件事,等这件事做完之后再去做另一件事
  • 所谓异步:就是一段时间内可以并发的做多件事
    我们可以拿生活中的事来解释:比如我们做饭(不仅仅只是煲饭这一个线程,还包括做菜),同步就是当我们把饭放在电饭锅里插上电,然后我们不用做任何事情,等饭堡熟了,我们再洗菜炒菜;异步就是但我们把饭堡在锅里之后,饭还在煮的同时我们可以洗菜,炒菜。生活中有好多例子可以来解释某些专业名称,这样更易于理解,我们这里主要来讲将线程的同步
    在大多数需要运行多线程的应用程序中,两个或多个线程需要共享对同一个数据的访问,如果每个线程都会调用一个修改该数据的方法,那么这些线程将会相互影响对方的行为,为了避免这种情况的发生,那么同步机制就产生了
    举一个示例来说明这个问题,有一奥运门票销售系统,它有5个销售点,共通销售100张奥运门票,用多线程来模拟这个销售系统的代码如下:
public class TicketOfficeTest {

	public static void main(String[] args) {
		TicketOffice off=new TicketOffice();
		Thread t1=new Thread(off);
		t1.setName("销售点1");
		t1.start();
		Thread t2=new Thread(off);
		t2.setName("销售点2");
		t2.start();
		Thread t3=new Thread(off);
		t3.setName("销售点3");
		t3.start();
		Thread t4=new Thread(off);
		t4.setName("销售点4");
		t4.start();
		Thread t5=new Thread(off);
		t5.setName("销售点5");
		t5.start();
		
	}

}
 class TicketOffice implements Runnable{
	 private int tickets=0;
	public void run() {
		boolean flag=true;
		while(flag) {
			flag=sell();
		}
		
	}
	public boolean sell() {
		boolean flag=true;
		if(tickets<100) {
			tickets=tickets+1;
			try {
				Thread.sleep(105);
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()
					+"卖出第"+tickets+"张票");
		}else {
			flag=false;
		}
		return flag;
		
	}
	 
 }
 其结果为:
 销售点4卖出第5张票
销售点3卖出第5张票
销售点5卖出第5张票
销售点1卖出第5张票
销售点2卖出第5张票
销售点2卖出第10张票
销售点4卖出第10张票
销售点3卖出第10张票
销售点5卖出第10张票
销售点1卖出第10张票
销售点2卖出第15张票
销售点4卖出第15张票
...

观察这个结果,发现不同销售点会重复售出同一张门票,这个显然不符合要求
所以为了解决这种问题,我们用同步机制,能保证当多个线程同时访问临界资源时,一个线程在执行的时候不会被打断,通过用关键字synchronized来加保护伞,synchronized主要用于应用于同步代码块和同步方法中

  • 同步方法:synchronized放在方法声明中,表示整个方法为同步方法
public synchronized boolean sell() {
		boolean flag=true;
		if(tickets<100) {
			tickets=tickets+1;
			try {
				Thread.sleep(105);
			}catch(InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()
					+"卖出第"+tickets+"张票");
		}else {
			flag=false;
		}
		return flag;
		
	}
	其结果为:
	销售点2卖出第1张票
销售点2卖出第2张票
销售点2卖出第3张票
销售点2卖出第4张票
销售点5卖出第5张票
销售点5卖出第6张票
销售点1卖出第7张票
销售点1卖出第8张票
销售点1卖出第9张票
销售点1卖出第10张票
...
  • 同步代码块:把线程体内的执行的方法中会操作到共享数据的语句封装在{}之内,然后用synchronized放在某个对象的前面修饰这个代码块
public boolean sell() {
		boolean flag=true;
		synchronized (this) {
			if(tickets<100) {
				tickets=tickets+1;
				try {
					Thread.sleep(105);
				}catch(InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()
						+"卖出第"+tickets+"张票");
			}else {
				flag=false;
			}
		}
		return flag;
	}

其结果和同步方法一样,只是同步了会操作到共享数据的代码,这种方法比同步整个方法会更有效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值