java进阶:15.2 多线程 - synchronized、线程安全类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/L20902/article/details/89305871


如果一个类的对象在多线程程序中没有导致竞争状态,则称这样的类为线程安全的( thread-safe) 。

多线程的同步问题指的是多个线程同时修改一个数据的时候,可能导致的问题多线程的问题,又叫 Concurrency 问题

1. 线程同步概念

当两个任务以一种会引起冲突的方式访问一个公共资源时,会引起竞争

package Thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AccountWithoutSync {

	private static Account account =  new Account();
	
	public static void main(String[] args) {
		ExecutorService executor = Executors.newCachedThreadPool();
		
		for(int i = 0; i < 100; i++)  //创建100 个在线程池executor 中执行的线程
			executor.execute(new AddPennyTask());
		
		executor.shutdown();
		while(!executor.isTerminated()) {  //测试线程是否终止
		}
		System.out.println("what is balance?" + account.getBalance());
	}
	
	
	private static class AddPennyTask implements Runnable{
		public void run() {
			account.deposit(1);
		}
	}
	

	private static class Account{
		private int balance = 0;
	
		public int getBalance() {
			return balance;
		}
	
		public void deposit(int amount) {
			int newBalance = balance + amount;
			
	
			try {
				Thread.sleep(5);
			}
			catch(InterruptedException ex) {
			}
	
			balance = newBalance;
		}	
	}
}

2. synchronized

为避免竞争状态,应该防止多个线程同时进入程序的某一特定部分,程序中的这部分称为临界区( critical regioD) 。

可以使用关键字synchronized 来同步方法,以便一次只有一个线程可以访问这个方法。

对于竞争冲突问题,有几种办法可以解决。

  1. 一种办法是通过在deposit 方法中添加关键宇synchronized ,使Account 类成为线程安全的.public synchronized void deposit(int amount)

  2. 一个同步方法在执行之前需要 加锁( 15.3内容 )

Object someObject =new Object();
synchronized (someObject){
        //此处的代码只有占有了someObject后才可以执行
}

synchronized 表示当前线程独占对象 someObject

当前线程独占了对象someObject,如果有其他线程试图占有对象someObject,就会等待,直到当前线程释放对someObject的占用。

someObject 又叫同步对象,所有的对象,都可以作为同步对象。为了达到同步的效果,必须使用同一个同步对象

释放同步对象的方式: synchronized 块自然结束,或者有异常抛出

 
 

3. 同步语句

当执行方法中某一个代码块时,同步语句不仅可用于对 this 对象加锁,而且可用于对任何对象加锁。这个代码块称为同步块。

 synchronized (expr) {
        statements;
  }

表达式expr 求值结果必须是一个对象的引用。如果对象已经被另一个线程锁定,则在
解锁之前,该线程将被阻塞。当获准对一个对象加锁时,该线程执行同步块中的语句,然后解除给对象所加的锁。
 
 

4. 线程安全类

如果一个类,其方法都是有synchronized修饰的,那么该类就叫做线程安全的类

同一时间,只有一个线程能够进入 这种类的一个实例 的去修改数据,进而保证了这个实例中的数据的安全(不会同时被多线程修改而变成脏数据)

比如StringBuffer和StringBuilder的区别
StringBuffer的方法都是有synchronized修饰的,StringBuffer就叫做线程安全的类
而StringBuilder就不是线程安全的类
 
 

猜你喜欢

转载自blog.csdn.net/L20902/article/details/89305871