Java使用synchronized进行多线程同步

        多个线程访问一些程序中的资源时,会发生资源抢占。我们用线程同步来解决这个问题,保证线程安全。

如果有一个全局变量 int sum = 1;有A,B两个线程对sum进行操作,他们获取资源时都是sum = 1,而线程A对其进行+1写回去变成了 2,如果我们希望线程B对其也进行+1操作后sum = 3,但是因为B线程获取到的是sum = 1,所以操作后写回去也是sum = 2 。为了解决类似的问题,引入了锁的概念——即在一个线程操作时进行锁定,暂时不给别的资源操作,直到其释放。

例子:使用synchronized进行同步

先看不加锁的情况:

class Total {
	private int sum;  //共享资源
	public Total() {
		this.sum = 0;
	}
	public int getSum() {
		return sum;
	}
	public void setSum(int sum) {
		this.sum = sum;
	}
	
	
}
class TotalTest implements Runnable {
	static final Total total = new Total();
	@Override
	public void run() {
		for(int i = 0;i<1000;i++) {
			total.setSum(total.getSum()+1);
		}
	}
	
}

public class T_test {
	
	public static void main(String[] args) {
		TotalTest tt1 = new TotalTest();
		/*
		 * 开了两个线程进行模拟 ,如果输出的sum结果不等于2000
		 * 那么就说明出现了线程安全问题
		 */
		Thread t1 = new Thread(tt1);
		Thread t2 = new Thread(tt1);
		t1.start();
		t2.start();
		try {
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(tt1.total.getSum());
	}

}

输出: 1181

解决方案:在访问共享资源的代码块外加上同步锁

class TotalTest implements Runnable {
	static final Total total = new Total();
	@Override
	public void run() {
		for(int i = 0;i<1000;i++) {
			synchronized (this) { //加入了实例锁
				total.setSum(total.getSum()+1);
			}
			
		}
	}
	
}

前面我们只实例化了一个线程实例,加实例锁可以解决线程同步问题。下面我们实例化两个线程对象

public class T_test {
	
	public static void main(String[] args) {
		TotalTest tt1 = new TotalTest();
		TotalTest tt2 = new TotalTest();
		/*
		 * 开了两个线程进行模拟 ,如果输出的sum结果不等于2000
		 * 那么就说明出现了线程安全问题
		 */
		Thread t1 = new Thread(tt1);
		Thread t2 = new Thread(tt2);
		t1.start();
		t2.start();
		try {
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(tt1.total.getSum());
	}

}

这时输出:1970

解决方案 :加上类级锁

public void run() {
		for(int i = 0;i<1000;i++) {
			synchronized (TotalTest.class) { //加上了TotalTest类级锁
				total.setSum(total.getSum()+1);
			}
			
		}
	}

输出:2000



猜你喜欢

转载自blog.csdn.net/bingocoder/article/details/80327902