自学java多线程(二)------线程的同步

1.线程同步方式synchronised

为什么要线程同步,举个简单的例子,你的银行账户一共有3000块钱,你的手里有这3000块的存折,你的妻子手里有这3000块的银行卡,你拿着存折到银行取2000块钱,与此同时,你的妻子拿着银行卡到取款机取2000块,你们两个人同时访问了同一个银行账户,访问的时候,余额都是3000块,当进行取钱操作的时候,系统会判断你的账户里的钱足够你和你妻子取出的数目,这样,账户就会同时给你和你妻子一人2000块,然后账户余额剩下1000,显然这对银行来说是亏损,为了避免这个情况,就需要线程同步。当你取钱的时候,访问这个账户的余额的同时给这个账户加上一把锁,在此期间其他人无法访问这个账户,直到这个锁失效,这样就达到了线程同步的目的。

看下面例子:

package Thread;

public class TestSync implements Runnable {
	Timer timer = new Timer();
	
	public static void main(String[] args) {
		TestSync test = new TestSync();
		Thread thread1 = new Thread(test);
		Thread thread2 = new Thread(test);
		
		thread1.setName("t1");
		thread2.setName("t2");
		
		thread1.start();
		thread2.start();
	}

	@Override
	public void run() {
		timer.addNum(Thread.currentThread().getName());
	}
	
}

class Timer{
	private int num = 0;
	public void addNum(String name){
		num++;
		try{
			Thread.sleep(1);
		}catch(Exception e){
			
		}
		System.out.println(name+",你是第"+num+"个访问timer的线程");
	}
}

输出结果:    t1,你是第2个访问timer的线程

                    t2,你是第2个访问timer的线程

很明显这不是我们想要的结果,期待的结果应该是:t1,你是第1个访问timer的线程,t2,你是第2个访问timer的线程。为什么会出现这种情况呢?当t1执行addNum的时候,num 变成了1,然后程序睡眠了1毫秒,此时t2访问addNum模块,num再次+1变为2,当t1继续执行的时候,num就变成了2.如果想要期待的输出结果,就需要线程同步,在上面的addNum方法上加一把锁。让addNum方法在同一时间只能有一个线程访问。代码如下

class Timer{
	private int num = 0;
	public void addNum(String name){
		synchronized (this) {
			num++;
			try{
				Thread.sleep(1);
			}catch(Exception e){
				
			}
			System.out.println(name+",你是第"+num+"个访问timer的线程");
		}
	}
}

当t1执行addNum方法时候,synchronized给当前对象上了锁,其他线程只能等到t1访问结束,才能访问addNum方法。

输出结果:    t1,你是第1个访问timer的线程

                    t2,你是第2个访问timer的线程

2.死锁

简单的来说就是两个拥有锁的资源互相访问。形成了死锁。看例子程序

package Thread;

public class TestDeadLock implements Runnable{
	public int flag = 1;
	static Object o1 = new Object(),o2 = new Object();
	@Override
	public void run() {
		System.out.println("flag=="+flag);
		if(flag == 1){
			synchronized(o1){
				try{
					Thread.sleep(500);
				}catch(Exception e){}
				synchronized(o2){
					System.out.println("1");
				}
			}
		}
		if(flag == 0){
			synchronized(o2){
				try{
					Thread.sleep(500);
				}catch(Exception e){}
				synchronized(o1){
					System.out.println("0");
				}
			}
		}
	}
	public static void main(String[] args) {
		TestDeadLock test1 = new TestDeadLock();
		TestDeadLock test2 = new TestDeadLock();
		test1.flag = 1;
		test2.flag = 0;
		Thread t1 = new Thread(test1);
		Thread t2 = new Thread(test2);
		
		t1.start();
		t2.start();
	}

}
上面程序中两个线程就形成了死锁,解决的办法是同步的颗粒度粗一点,不要给对象加锁,最好给代码块加锁。至于其他的解决方法也很多,就介绍了。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值