java高并发程序设计学习笔记(四)

synchronized

在并发程序设计中,线程的安全无疑是极为重要的。保证了性能的同时也必须保证安全性。线程安全是并行程序的基础。加入了volatile关键字并不能绝对保证线程安全,他的作用只是让这个变量对于线程来说是变化可见的。上篇提到过。如果要保证线程的安全那么synchronized则是一大利器。

上文我们已经提过了volatile如果遇到多个线程同时修改,那么他并不能保证自己的线程安全。要从根本上解决问题就必须保证多个线程对变量的操作完全同步。当a线程使用变量资源的时候,其他任意资源都不能访问这个变量。

synchronize是对资源的加锁操作,保证线程的安全。因此我们来优化一下上篇的代码。

public class Main implements Runnable{	
	static Main ins = new Main();	
	static volatile int j = 0;	
	public static void main(String[] args) {		
		Thread t1 = new Thread(ins);		
		Thread t2 = new Thread(ins);		
		t1.start();		
		t2.start();		
		try {			
			t1.join();			
			t2.join();		
		}catch(InterruptedException e) {			
			e.printStackTrace();		
		}		
		System.out.println(j);	
	} 	
	public void run() {		
		for(int i = 0;i < 100000;i++) {			
			synchronized(ins) {				
				j++;			
			}		
		}	
	}
}

也就是在run方法里给j++这个操作加锁,使得任意线程进来执行这个方法都需要获取当前这个对象的锁,因此j++这个操作就被同步了。于是就这样保证了线程的安全。
synchronized还可以写成其他形式,我们把上述代码的后段重写一下。

public synchronized void sum() {		
	j++;	
}	
public void run() {		
	for(int i = 0;i < 100000;i++) {			
		sum();		
	}	
}

关于加锁的方式有很多需要注意的,以下这种是错误的加锁方式。

public class Main implements Runnable{	
	static Main ins = new Main();	
	static volatile int j = 0;	
	public static void main(String[] args) {		
		Thread t1 = new Thread(new Main());		
		Thread t2 = new Thread(new Main());		
		t1.start();		
		t2.start();		
		try {			
			t1.join();			
			t2.join();		
		}catch(InterruptedException e) {			
			e.printStackTrace();		
		}		
		System.out.println(j);	
	}
	public synchronized void sum() {		
		j++;	
	}	
	public void run() {		
		for(int i = 0;i < 100000;i++) {			
			sum();		
		}	
	}
}

乍一看好像一点问题都没有。但问题的关键是在创建线程的地方,传入的参数是新创建的对象。也就是synchronized在加锁的过程中,锁住的是各自新创建出来的对象的锁。也就是这两个锁,锁住了两个不同的对象,自然会导致线程的不安全。
但我们只需要做一些小小的改动。

public static synchronized void sum() {  
  	j++; 
}

这样就算两个线程持有不同的锁,但这个方法需要请求当前类的锁,所以线程还是可以实现同步。从可见性上,synchronized可以完全代替volatile。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值