线程的同步(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关键字在同一时间只允许一个线程进行操作,属于串行操作,保证线程间的有序性。

参考链接

猜你喜欢

转载自www.cnblogs.com/kungFuPander/p/11711713.html