Java高并发编程学习--7. 线程的synchronized关键字

一、synchronized关键字

    1. synchronized关键字提供一种锁的机制,确保共享变量的互斥访问,防止数据不一致
    1. synchronized关键字包括monitor enter和monitor exit两个JVM指令,能够保证在任何时候任何线程执行到monitor enter成功之前都必须从主内存中获取数据,而不是从缓存中,在monitor exit运行成功之后,共享变量被更新后的值必须存入主存
    1. synchronized的指令严格遵守java happens-before规则,一个monitor exit指令之前必定要有一个monitor enter

二、叫号例子

package safe;

/**
 * @ClassName TicketWindowRunnable
 * @Description TODO
 * 1. synchronized关键字提供一种锁的机制,确保共享变量的互斥访问,防止数据不一致
 * 2. synchronized关键字包括monitor enter和monitor exit两个JVM指令,能够保证在
 * 任何时候任何线程执行到monitor enter成功之前都必须从主内存中获取数据,而不是从
 * 缓存中,在monitor exit运行成功之后,共享变量被更新后的值必须存入主存
 * 3. synchronized的指令严格遵守java happens-before规则,一个monitor exit指令
 * 之前必定要有一个monitor enter
 * @Author Cays
 * @Date 2019/3/11 12:15
 * @Version 1.0
 **/
public class TicketWindowRunnable implements Runnable {
    //synchronized叫号程序
    private int index=1;
    private final static int MAX=500;
    public final static Object MUTEX=new Object();
    @Override
    public void run() {
        //互斥机制,同一时刻只能有一个线程访问同步资源
        //锁不正确,而是线程获取了与mutex关联的monitor锁
        synchronized (MUTEX) {
            while (index <= MAX) {
                System.out.println(Thread.currentThread() + "的号码是:" + (index++));
            }
        }
    }
    public static void main(String []args){
        final TicketWindowRunnable task=new TicketWindowRunnable();
        Thread win1=new Thread(task,"一号窗口");
        Thread win2=new Thread(task,"二号窗口");
        Thread win3=new Thread(task,"三号窗口");
        Thread win4=new Thread(task,"四号窗口");
        win1.start();win2.start();
        win3.start();win4.start();
    }
}

三、运行结果

在这里插入图片描述

四、synchronized需要注意的问题

package safe;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName Mutex
 * @Description TODO
 * 1. monitor enter
 * 每一个对象都与一个monitor相关联,一个monitor的lock锁只能被一个线程在同一时间获得,
 * 在一个线程尝试获得与关联monitor的所有权时会发生如下几件事:
 * (1)如果monitor的计数器为0,则意味着该monitor的lock还没有被获得,某个线程获得后立即对
 * 该计数器加一,该线程成了该monitor的所有者
 * (2)如果一个已拥有该monitor所有权的线程重入,则会导致monitor计数器累加
 * (3)如果monitor已经被其他线程所拥有,则其他线程尝试获取该monitor的所有权时,
 * 会被阻塞到monitor的计数器变为0,才能再次尝试获取该monitor的所有权
 * 2. monitor exit
 * 释放对monitor的所有权,将monitor计数器减一
 * @Author Cays
 * @Date 2019/3/11 12:39
 * @Version 1.0
 **/
public class Mutex {
    // synchronized需要注意的问题
    // 1. 与monitor关联的对象不能为空 private final Object mutex = null
    // 2. synchronized作用域太大(串行代码效率低)
    // 3. 不同的monitor企图锁同一个方法(自定义的thread实现Runnable接口)
    // 4. 锁交叉导致死锁
    private final static Object MUTEX=new Object();
    public void accessResource(){
        synchronized (MUTEX){
            try {
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String []args){
        final Mutex mutex=new Mutex();
        for (int i=0;i<5;i++){
            new Thread(mutex::accessResource).start();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值