zoukankan      html  css  js  c++  java
  • Java Threads -- 数据同步(1)

    一、synchronized关键字

    1、先来看一个定义,互斥锁,也叫互斥排它锁,是很多线程系统来用来实现同步的一种方式。在某一时刻,只能有一个线程可以占有这种锁,如果有多个线程试图去占有一个互斥锁时,最终只有一个线程可以成功,其他的必须等待,直到占有成功的那个线程释放锁以后,其他的线程才可以占有锁然后执行后续操作。

    2、在java中,每个对象都有一个关联的锁,当一个方法被声明为synchronized的时候,执行方法的线程必须先占有到这个对象上关联的锁,然后才能执行这个方法,当方法执行结束,执行线程会释放这把锁。

    3、java中的每个对象都有且只有一把锁,如果两个线程同时调用同一个对象上的声明为synchronized的方法时(可以是同一个方法或者不同的方法),只有一个线程可以执行,另一个必须等待,直到第一个线程执行完它的方法后,等待的线程才可以执行它的方法。

    二、volatile关键字

    1、再看一个定义,锁的范围:锁被占有和释放之间的一段时间。比如同步方法,这些方法里的锁的范围,就是执行方法所用的时间,我们称之为方法范围。我们还可以给代码块上锁,或者显式地去占有和释放一个锁,这些锁的范围是不同的,这个后面再讲。

    2、java规定对基本变量的值进行读取或者保存必须是原子操作的(long和double类型变量除外)。

    2、java的内存模型,可以允许线程保存变量的值到本地内存(local memory,比如机器的寄存器)。这样就产生了一个问题,一个线程更改了变量的值而另一个线程完全不知道变量的值被改变了。

      解决这个问题的一个方法就是为变量定义同步的getter和setter方法,使用方法来读取和设置变量的值,这样能够成功,是因为获取一个同步锁的时候,所有在寄存器中的临时变量都会更新到主存中。

    3、解决上面问题的另一个方法是使用volatile关键字,用volatile标记的变量,在每次被使用的时候都是从主存里获取的,在每次被赋值的时候,也会更新到主存中。

    4、volatile变量只是解决由java内存模型引起的这个问题,只能在对变量的操作都是原子操作的时候使用,也就是说使用变量的方法中,只能简单地对变量进行读值或者赋值,如果方法中还存在其他代码,代码的执行不能基于变量的值的改变而改变,比如自增(++)和自减(--)操作不能使用在volatile变量上,因为这些操作被称为语法糖,不是原子操作,而是包括读取,改变,赋值三个操作。

    5、volatile变量有着严格的使用要求,它是否重要是个无止境的争论,不过我们现在把它认为是强迫java虚拟机不对变量使用临时的副本,都是直接从主存进行读写。虽然你可能不一定使用这种类型变量,但是它也是在程序设计时的一种选择。我们以后会讲到一种功能类似的变量,叫原子变量,它的使用没有这么多严格的要求。

    6、数组也可以使用volatile,表示数组的引用是volatile,数组的元素不是volatile的,虚拟机还是可能把数组元素保存在寄存器中。这个时候如果有多线程来访问数组中的元素,就必须使用synchronized关键字了,这种情况下,使用原子变量也会有所帮助。

  • 相关阅读:
    redis
    libevent简述
    IPC-本地套接字
    广播和组播
    UDP实现并发服务器
    select
    epoll
    BUUCTF-[极客大挑战 2019]HardSQL 1
    CTFHUB-Injection V2.0
    SQL注入中登录框只验证用户名情况下的绕过
  • 原文地址:https://www.cnblogs.com/winson/p/3611932.html
Copyright © 2011-2022 走看看