线程的同步(Java内存模型)

线程的同步

保证多线程安全访问竞争资源的一种手段,避免多个线程同时修改一个资源,导致资源的不正确性。

相关概念

  • 什么是竞争资源
  • 什么时候需要同步
  • 要怎样进行同步
  1. 将竞争资源标为private
  2. 将涉及到静态资源的方法或块用synchrized关键字修饰

同步方法

模拟银行转账功能

package cn.domin.threadr.sync;
public class Thransfer {
		User u = new User();
		u.setBalance(10000);
		u.setCode(0x08);
		
		ATMThread a1 = new ATMThread("ATM1", u, 1000);
		ATMThread a2 = new ATMThread("ATM2", u, 5000);
		ATMThread a3 = new ATMThread("ATM3", u, 3000);
		a1.start();
		a2.start();
		a3.start();
	}
}
class ATMThread extends Thread{
	private User u;
	private int y;
	public ATMThread(String name,User u,int y) {
		super(name);
		this.u = u;
		this.y = y;
	}
	
	public void oper(int y) {
		int m = u.oper(y);
		System.out.println(Thread.currentThread().getName()+"操作"+y+"元,账户余额"+m+"元");
	}
	
	public void run() {
		oper(y);
	}
	
}

class User{
	private int code;
	private int balance;
	
	public synchronized int oper(int y) {
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		balance += y;
		return balance;
	}

	public int getCode() {
		return code;
	}

	public void setCode(int code) {
		this.code = code;
	}

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		this.balance = balance;
	}
}

volitile关键字

  • 修饰的变量在同一时间只能由一个线程进行操作
  • 需要注意的是,当变量的值和自身上一个值无关时,所做的操作才是原子级别的
  • 原子操作,是指不会被线程调度打断的操作,该线程
  • volatile属性操作并不能保证操作的原子性,可使用synchronized关键字、锁机制、同步类来保证操作的原子性。
public class Thransfer {
	
	private volatile int it;
	
	public static void main(String[] args) {
		User u = new User();
		u.setBalance(10000);
		u.setCode(0x08);
		
//		ATMThread a1 = new ATMThread("ATM1", u, 1000);
//		ATMThread a2 = new ATMThread("ATM2", u, 5000);
//		ATMThread a3 = new ATMThread("ATM3", u, 3000);
//		a1.start();
//		a2.start();
//		a3.start();
		final Thransfer t = new Thransfer();
		for (int i = 0; i < 100; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					t.cre();
				}
			}).start();
		}
		while(Thread.activeCount()>1) {
			Thread.yield();
		}
		System.out.println(t.it);
	}
	
	public synchronized void cre() {
		this.it++;
	}
}

概念知识
Java内存模型:

  1. 可见性
    线程之间的修改状态是可见的。也就是说一个线程修改的结果,另一个线程是立马可见的。比如volitile关键字,其修饰的变量不允许线程缓存和重排序,所以对其他线程是可见的,要注意不可分割性。
  2. 原子性
    原子是世界上最小的单位,具有不可分割性,那么我们称不可分割的操作为原子操作,n++和n=n+1都不属于原子操作,因为他是分割的。
  3. 有序性
    java提供二种方式来保证xi线程操作之间的有序性
  4. volitile本身具有禁止指令重拍的语义
  5. synchronization关键字在同一时间只允许一个线程进行操作,属于串行操作,保证线程间的有序性。

参考链接

posted @ 2019-10-21 09:48  kungFuPander  阅读(231)  评论(0编辑  收藏  举报