可见性
1
|
Java内存模型(JMM)规定了jvm有主内存,主内存是多个线程共享的。当 new 一个对象的时候,也是被分配在主内存中,<br> 每个线程都有自己的工作内存,工作内存存储了主存的某些对象的副本,当然线程的工作内存大小是有限制的。
|
(1) 从主存复制变量到当前工作内存 (read and
load)
(2) 执行代码,改变共享变量值 (use and assign)
(3)
用工作内存数据刷新主存相关内容 (store and write)
有序性
线程在引用变量时不能直接从主内存中引用,如果线程工作内存中没有该变量,则会从主内存中拷贝一个副本到工作内存中,这个过程为read-load,完成后线程会引用该副本。当同一线程再度引用该字段时,有可能重新从主存中获取变量副本(read-load-use),也有可能直接引用原来的副本(use),也就是说 read,load,use顺序可以由JVM实现系统决定。 线程不能直接为主存中中字段赋值,它会将值指定给工作内存中的变量副本(assign),完成后这个变量副本会同步到主存储区(store-write),至于何时同步过去,根据JVM实现系统决定.有该字段,则会从主内存中将该字段赋值到工作内存中,这个过程为read-load,完成后线程会引用该变量副本,当同一线程多次重复对字段赋值时
public class Account { private int balance; public Account(int balance) { this.balance = balance; } public int getBalance() { return balance; } public synchronized void add(int num) { balance = balance + num; System.out.println(Thread.currentThread().getName() + "-" + balance); } public synchronized void withdraw(int num) { balance = balance - num; System.out.println(Thread.currentThread().getName() + "-" + balance); } public static void main(String[] args) throws InterruptedException { Account account = new Account(1000); Thread a = new Thread(new AddThread(account, 20), "add"); Thread b = new Thread(new WithdrawThread(account, 20), "withdraw"); a.start(); b.start(); a.join(); b.join(); System.out.println(account.getBalance()); } static class AddThread implements Runnable { Account account; int amount; public void run() { for (int i = 0; i < 200000; i++) { account.add(amount); } } public AddThread(Account account, int amount) { this.account = account; this.amount = amount; } } static class WithdrawThread implements Runnable { Account account; int amount; public WithdrawThread(Account account, int amount) { this.account = account; this.amount = amount; } public void run() { for (int i = 0; i < 100000; i++) { account.withdraw(amount); } } } }
只有在对象锁池中的线程才有机会获得对象锁.执行同步代码块.
如果需要获得对象锁.线程需要从等待池.-移动->锁池-进一步->获得对象锁.
释放对象的锁<以下情况会释放对象锁>
1 执行完同步代码块就会释放锁
2 执行同步代码块过程中,遇到异常而导致线程终止锁被释放
3 在执行同步代码块过程中,遇到wait().执行该方法的线程
释放对象的锁.把该县城放到该对象的等待池中.