java多线程volatile,synchronized

 

1.特殊域变量(volatile)实现线程同步,只能修饰类中变量上,不能为final修饰

a.volatile关键字为域变量的访问提供了一种免锁机制,

b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,

c.因此每次使用该域就要重新计算,而不是使用寄存器中的值

d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量;

e.volatile保证了修改的可见性,一个线程对这个变量进行了修改,其他引用这个变量的线程,立即会获取到修改之后的值;

/**
 *@Author Thomas 2019-11-26 15:01
 * The world of programs is a wonderful world
 */
public class Main {

    private volatile int count=100;

    public int countT(int count1){
        System.out.println("原值 "+Thread.currentThread().getName()+" "+count+" count="+count1);
        count=count+count1;
        System.out.println("新值 "+Thread.currentThread().getName()+" "+count+" count="+count1);
        return count;
    }

    public static void main(String[] args) {
        Main main=new Main();
        new Thread(new Runnable() {
            @Override
            public void run() {
                int count = main.countT(1);
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                int count = main.countT(3);
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                int count = main.countT(2);
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                int count = main.countT(5);
            }
        }).start();
    }
}





加上关键字修饰之后,出现同步,未加关键字出现不同步的 情况
out:
原值 Thread-0 100 count=1
新值 Thread-0 101 count=1
原值 Thread-2 101 count=2
原值 Thread-1 101 count=3
新值 Thread-1 106 count=3
新值 Thread-2 103 count=2
原值 Thread-3 106 count=5
新值 Thread-3 111 count=5

2.线程之间的同步互斥,需要使用到关键字来保护需要同步的代码,

synchronized,要保证互斥的线程使用同一把锁,才可以实现互斥的效果,
作用到方法上,锁就是当前对象
作用到静态方法上,锁就是类,所有调用这个方法的方法,都是同步的
作用到代码块上,需要设置锁;
可以作用到静态代码块中
static {
        synchronized (Main.class){
            
        }
    }
public void print(String name){
    int len=name.length();
    synchronized (this){
        for (int i=0;i<len;i++){
            System.out.print(name.charAt(i));
        }
        System.out.println();
    }

}

 

方法是对象调用,锁要加同一个对象,也就是需要加同一把锁
public synchronized void print1(String name){
    int len=name.length();
        for (int i=0;i<len;i++){
            System.out.print(name.charAt(i));
        }
        System.out.println();
}

解释以下名词:重排序,自旋锁,偏向锁,轻量级锁,可重入锁,公平锁,非公平锁,乐观锁,悲观锁

重入锁(ReentrantLock是一种递归无阻塞的同步机制。重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁。

自旋锁,由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。如何旋转呢?何为自旋锁,就是如果发现锁定了,不是睡眠等待,而是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。

偏向锁(Biased Locking)是Java6引入的一项多线程优化,它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。 如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁。

轻量级锁是由偏向所升级来的,偏向锁运行在一个线程进入同步块的情况下,当第二个线程加入锁争用的时候,偏向锁就会升级为轻量级锁。

重入锁(ReentrantLock)是一种递归无阻塞的同步机制,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。 在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁。

公平锁,就是很公平,在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程线程是等待队列的第一个,就占有锁,否则就会加入到等待队列中,以后会按照FIFO的规则从队列中取到自己

非公平锁比较粗鲁,上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式。

 

感谢作者提供  https://www.cnblogs.com/tison/p/8283233.html

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值