共享模型之管程

临界区

一个程序运行多个线程是没问题的,问题出现在多个线程访问同一个共享资源

多线程访问同一个共享资源也没有问题,问题在于线程再执行读写操作时会有指令交错,那么就会出现问题

一段代码如果存在线程对共享资源的访问,那么就称这段代码块为临界区

static int counter = 0; static void increment() // 临界区 { counter++; } static void decrement() // 临界区 { counter--; }

竞争条件

多个线程在临界区执行时,它们的执行顺序是不清楚的,所以才会有产生竞争条件

synchronized互斥锁解决方案

应用之互斥

为了避免临界区的竞争条件发生,有多种手段可以达到目的

阻塞式的解决方案:synchronized、lock

非阻塞式的解决方案:原子变量

而synchronized(对象锁),采用了互斥的方式让同一时刻只有一个线程才能拥有对象锁,其他线程再想获取这个对象锁时就会阻塞住,这样就能保证拥有锁的线程可以安全执行临界区内的代码,不用担心线程上下文之间的切换

这里注意一个点:

互斥是保证临界区的竞争条件发生时,同一时刻只有一个线程去执行

同步是由于线程执行的先后顺序不同,需要一个线程等待其他线程运行到某个点

其实使用synchronized就是用对象锁来保证了临界区的代码块的原子性,临界区的代码对外是不可分割的,不会被线程切换所打断

如果把 synchronized(obj) 放在 for 循环的外面,如何理解?-- 原子性

如果 t1 synchronized(obj1) 而 t2 synchronized(obj2) 会怎样运作?-- 锁对象

如果 t1 synchronized(obj) 而 t2 没有加会怎么样?如何理解?-- 锁对象

变量的线程安全分析

成员变量和静态变量是否线程安全?

如果它们没有被共享,那么就线程安全;如果它们被共享了,并且只进行读操作,那么就是线程安全,如果进行写操作,就是线程不安全

局部变量是否线程安全?

局部变量是线程安全的;但局部对象引用的对象未必是线程安全的,如果该对象没有逃离方法的作用区域,那么就是线程安全的,如果逃离 方法的作用区域,就是线程不安全的

常见的线程安全类:

Wait&Notify

sleep和wait的区别:

1、sleep是Thread方法,而wait是Object方法

2、sleep不需要强制和synchronized一起使用,而wait需要和synchronized一起使用

3、sleep时线程不会释放锁,而wait会使线程释放锁

Park和UnPark:

它们是LockSupport类的方法,目的是暂停当前线程,当是不会释放锁,会阻塞其他同步线程运行

这里调用这些方法需要重新理解线程状态转换

ReentranLock

相对于synchronized它有这方面特点:

可中断、可设置超时时间、可设置为公平锁、支持多个条件变量

基本语法为:

// 获取锁 reentrantLock.lock(); try { // 临界区 } finally { // 释放锁 reentrantLock.unlock(); }

条件变量

synchronized只能有一个条件变量去控制线程的指向,当线程获取不了这个条件变量时,那么就会发生阻塞;而ReentranLock可以拥有多个

条件变量,

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值