线程与锁

进程与线程

说到锁那么肯定要说进程与线程,现代操作系统的最小调度单位就是线程,最小的资源分配单位是进程,但是进程作为线程的存活依附,不能不说。(以下原理依附与java)

进程

什么是进程

进程是对计算机cpu的一种抽象
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动.

进程的生命周期与状态转化

进程在其生命周期内,由于各个进程之间的相互制约关系,状态也不断地发生变化:
- 创建:进程正在被创建,尚未抓到就绪状态,创建进程需要一下几个步骤:

  1. 申请一个空白的PCB(进程控制块);
  2. 为进程分配资源;
  3. 初始化PCB;
  4. 将新的进程插入就绪队列;

    • 就绪:进程已经处于准备运行的状态,进程获得cpu以外的一切资源,一旦处理时机到了就会运行。
    • 运行:进程运行,单核cpu一次只能处理一个进程。
    • 阻塞:进程等待某一事件而暂停运行,(如io操作时)就算cpu 空闲也不能运行。
    • 结束:进程正从系统中消失,这可能是进程正常结束或其他原因中断退出运行。当进程需要结束运行时,系统首先必须置该进程为结束状态,然后再进一步处理资源释放和回收等工作。
进程状态转化图:

image

线程

每个进程中可以创建多个线程,这些线程都拥有各自的计数器,堆栈,局部变量等属性,cpu在执行时,在这些线程之间告诉切换,让人感觉到线程之间是同事执行的;

线程的生命周期
  • 创建:TCB
  • 运行:java线程将操作系统中的就绪和运行笼统的成为(运行中)
  • 阻塞:阻塞状态发生有一下情况可能:

    1. 调用sleep(毫秒数),使线程进入“睡眠”状态。在规定的时间内,这个线程是不会运行的。
    2. 用suspend()暂停了线程的执行。除非线程收到resume()消息,否则不会返回“可运行”状态。
    3. 用wait()暂停了线程的执行。除非线程收到nofify()或者notifyAll()消息,否则不会变成“可运行”.
    4. 线程正在等候一些 I/O(输入输出)操作完成。
    5. 线程试图调用另一个对象的“同步”方法,但那个对象处于锁定状态,暂时无法使用。
  • 结束:当前线程任务执行完。

线程状态转换图:

image

刚才说了说到锁就不得不说线程,那么我们基本看完了线程,的生命周期和状态转化,那么为了让我们更清楚的了解到线程为什么会阻塞?我们需要看看那几种方法了:
每个对象都有唯一的一个monitor(个人理解为唯一标识符)
- sleep():

  1. 它是来自Thread类,调用sleep(long行参数)处于等待状态。
  2. 虽然当前线程进入了睡眠状态,但是依然持有monitor对象
  3. 自动进入唤醒状态从而继续执行代码。

    • wait():
  4. 他属于Object()类的方法,调用wait()后当前线程处于等待状态。

  5. 每一个线程都必须持有该对象的monitor,当前线程调用wait()方法后,这个线程就会释放monitor的持有对象并让自己处于等待状态。
  6. 如果想唤醒一个正在等待的线程,那么需要开启一个线程通过notify()或者notifyAll()方法去通知正在等待的线程获取monitor对象。如此,该线程即可打破等待的状态继续执行代码。
 private final Object object = new Object();  

 public void startThread() {  
        Thread t = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                System.out.println("进入等待状态。。。");  
                synchronized (object) {  
                    try {  
                        object.wait();  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                }  
                System.out.println("线程结束。。。");  
            }  
        });  
        t.start();  
    }  
  • suspend():官方已经不推荐使用这个方法了。

    1. 它是来自Thread类,直接调用就可以了t.suspend()
    2. 它使线程暂停,但是不释放任何锁资源,其他线程都无法访问被它占用的锁,直到对应的线程执行 resume() 方法后,被挂起的线程才能继续,从而其它被阻塞在这个锁的线程才可以继续执行。
    3. 如果 resume() 操作出现在suspend()之前执行,那么线程将一直处于挂起状态,同时一直占用锁,这就产生了死锁。

线程就先说到这里,刚才已经开始提到锁了,那么现在开始看锁吧!

说到锁,那么肯定是来处理并发事件的,那么处理并发事件就不得先来看看java的内存模型:(Java Memory Model)

内存模型(线程间通信)

Java内存模型用来屏蔽各种硬件和操作系统的内存访问差异,以实现在各种平台下都能达到一致的并发效果。主要目标是/定义程序中各个变量的/访问规则,即在虚拟机中/将变量存储到内存和从内存中取出变量这样的底层细节。

Java内存模型规定:
  • 所有的变量都存储在主内存中;
  • 每个线程有自己的工作内存,线程的工作内存保存被线程使用到变量的主内存副本拷贝;
  • 线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存的变量;
  • 不同线程之间不能直接访问对方工作内存中的变量,线程间变量值的传递通过主内存来完成。
工作内存与主内存之间的交互

image

他们之间的交互过程定义了如下操作:(以下操作皆为原子性操作)
1. lock(锁定):作用于主内存的变量,它把一个变量标识为一个线程独占的状态;
2. unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定;
3. read(读取):作用于主内存的变量,它把一个变量的值从主内存传送到线程中的工作内存,以便随后的load动作使用;
4. load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中;
5. use(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎;
6. assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存中的变量;
7. store(存储):作用于工作内存的变量,它把工作内存中的一个变量的值传送到主内存中,以便随后的write操作;
8. write(写入):作用于主内存的变量,它把store操作从工作内存中得到的变量的值写入主内存的变量中。、

操作规则

  • 不允许read和load、store和write操作之一单独出现;(读入工作内存就要给我写回主内存)
  • 不允许一个线程丢弃它的最近的assign操作,变量在工作内存中改变了之后必须把变化同步回主内存;(如有赋值操作,必须回写进主内存)
  • 不允许一个线程无原因地把数据从线程的工作内存同步回主内存;
  • 不允许在工作内存直接使用一个未被初始化(load或assign)的变量,即在对一个变量实施use和store操作之前,必须先执行assign和load操作;
  • 不允许同一变量在同一时刻,有其它线程对其lock操作,但lock操作可以被同一线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才被解锁;
  • 一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值;
  • 一个变量事先没有被lock操作锁定,则不允许对他执行unlock操作;也不允许去unlock一个被其他线程锁定住的变量;
  • 对一个变量执行unlock操作之前,必须先把此变量同步回主内存。

sychronized

volatile

说到volatile人们都称它为轻量级锁,但是最好不要称为锁为好,他只是同步机制的一种手段。

变量可见性
  • 可见性是指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。
禁止指令重排序

说到禁止指令重排序那就要先说说,编译器或者CPU的一种优化方式了,我觉得这个人讲的挺好的Java内存模型和线程安全:

未完待续。。。。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值