多线程并发的解决方案 volatile synchronized notify notifyAll wait关键字分析

1.ThreadLocal用法

在java中,如果一个变量需要被多个线程访问,可以使用volatile来声明它为“易变的”。而假如一个变量要被持有它的某个线程独享,在java中,它可以使用java.lang.ThreadLocal类来实现线程本地存储的功能。这样,数据便只在同一个线程内可见和共享,因此,即便不同步也能保证线程之间不出现数据争用。

ThreadLocal使得各线程能够保持各自独立的一个对象,通过ThreadLocal.set()来设置对象的值,保存在每个线程自己都有的一个map对象当中,每个ThreadLocal对象会有一个线程范围内唯一hashcode作为key,ThreadLocal.get()内部通过这个key从map中取值,因此取出来的是各自自己线程中的对象,ThreadLocal实例事实上只是作为map的key来使用的

 

ThreadLocal例子

package com.arch.demo;

public class ThreadLocalTest {

    public static void main(String[] args) {
        ThreadLocal<Integer> count = new ThreadLocal<>();

        ConcurrentThread t1 = new ConcurrentThread(count);
        ConcurrentThread t2 = new ConcurrentThread(count);
        ConcurrentThread t3 = new ConcurrentThread(count);
        ConcurrentThread t4 = new ConcurrentThread(count);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }


   static class ConcurrentThread extends Thread {

        ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

        private ConcurrentThread(ThreadLocal<Integer> count) {
            this.threadLocal = count;
        }

        @Override
        public void run() {
            for (int i = 1; i < 10; i++) {
                if (threadLocal.get() != null) {
                    threadLocal.set(threadLocal.get() + 1);
                } else {
                    threadLocal.set(1);
                }
                System.out.println("Thread:" + this.currentThread().getName() + ",Count:" + threadLocal.get());
            }
        }
    }
}

 

2.volatile用法

volatile是轻量级的synchronized, 它在多处理器开发中保证了共享变量的"可见性", 可见性是指一个线程在修改共享变量的值时,其他的线程可以读到这个修改的值

 

3.Synchronized与ReentranckLock区别

 

  1. Lock和 synchronized 有一点明显的区别 —— lock 必须在 finally 块中释放 

    2. Lock可以实现公平锁或不公平锁,而Synchronized是不公平的,而且永远都是不公平的。但 JVM 保证了所有线程最终都会得到它们所等候的锁,但是Lock作为默认设置,把公平设置为false 

     3. Lock性能和伸缩性都比较好(在JDK5.0),但是大多数情况Synchronized就足够了,而且更容易理解

     4.ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”。也就是说ReentrantLock在同一个时间点只能被一个线程获取

 

4. 重要点

  1).当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块

public class SynchronizedThread implements Runnable {
    @Override
    public void run() {
        synchronized (this){
            for(int i = 0; i < 5; i++){
                System.out.println(Thread.currentThread().getName() + " synchronized loop" + i);
            }
        }
    }

    public static void main(String[] args) {
        Runnable runnable = new SynchronizedThread();

        new Thread(runnable,"a").start();
        new Thread(runnable,"b").start();
    }
}

 

  2).当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块

 

 

 

 

转载于:https://my.oschina.net/chenxiaobian/blog/633635

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值