线程的同步和异步理解

//当个线程访问同一个资源的时候,要注意线程同步的问题,如果不同步容易造成数据没及时修改,然后就被另一个线程访问,得到的数据还是上一次的数据,造成数据错误的情况,以下demo可以很容易发现,为了便于发现我在上面休眠100毫秒,如果将ticket设为方法内的局部变量则就不会共享了。


package study0915;
public class ThreadTest implements Runnable{
	private int ticket = 5;//卖票
	
	/**
	 * 情景模拟:假设四个线程去执行卖票的功能,其中票为共享数据 
	 */
	
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			if(ticket>0){
				try {
					Thread.sleep(1000);
					ticket--;
					System.out.println(Thread.currentThread().getName() +"剩余票数" + ticket);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void main(String[] args) {
		ThreadTest th = new ThreadTest();
		new Thread(th,"A线程对象").start();
		new Thread(th,"B线程对象").start();
		new Thread(th,"C线程对象").start();
		new Thread(th,"D线程对象").start();
	}
D线程对象剩余票数1
B线程对象剩余票数1
A线程对象剩余票数1
C线程对象剩余票数1
D线程对象剩余票数0
C线程对象剩余票数-3
A线程对象剩余票数-2
B线程对象剩余票数-1

原因:
当多个线程访问统一资源,当A线程进入访问,休眠,其它线程也进来了,也休眠,但当都自醒后,可能线程1k快点,已经做了--的操作,但是取得的当前线程只有一个,所以不知道前面几个线程做了--的操作,这也就是数值不是按照43210-1-2-3这样排过来而是无序输出,这也是异步高效但是数据不同步的原因。

	
}
解决办法
//1.加入同步代码块
			synchronized (this) {
				if(ticket>0){
					try {
						Thread.sleep(1000);
						ticket--;
						System.out.println(Thread.currentThread().getName() +"剩余票数" + ticket);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
//2.同步方法   上锁  单独将方法抽出来
public static synchronized void test(){
		if(ticket>0){
			try {
				Thread.sleep(1000);
				ticket--;
				System.out.println(Thread.currentThread().getName() +"剩余票数" + ticket);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

猜你喜欢

转载自blog.csdn.net/qq_40826106/article/details/82745620
今日推荐