线程的同步(Java内存模型)
线程的同步
保证多线程安全访问竞争资源的一种手段,避免多个线程同时修改一个资源,导致资源的不正确性。
相关概念:
- 什么是竞争资源
- 什么时候需要同步
- 要怎样进行同步
- 将竞争资源标为private
- 将涉及到静态资源的方法或块用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内存模型:
- 可见性
线程之间的修改状态是可见的。也就是说一个线程修改的结果,另一个线程是立马可见的。比如volitile关键字,其修饰的变量不允许线程缓存和重排序,所以对其他线程是可见的,要注意不可分割性。 - 原子性
原子是世界上最小的单位,具有不可分割性,那么我们称不可分割的操作为原子操作,n++和n=n+1都不属于原子操作,因为他是分割的。 - 有序性
java提供二种方式来保证xi线程操作之间的有序性 - volitile本身具有禁止指令重拍的语义
- synchronization关键字在同一时间只允许一个线程进行操作,属于串行操作,保证线程间的有序性。