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

1.ThreadLocal用法

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

ThreadLocal使得各线程可以保持各自独立的一个对象,经过ThreadLocal.set()来设置对象的值,保存在每一个线程本身都有的一个map对象当中,每一个ThreadLocal对象会有一个线程范围内惟一hashcode做为key,ThreadLocal.get()内部经过这个key从map中取值,所以取出来的是各自本身线程中的对象,ThreadLocal实例事实上只是做为map的key来使用的并发

 

ThreadLocal例子ide

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, 它在多处理器开发中保证了共享变量的"可见性", 可见性是指一个线程在修改共享变量的值时,其余的线程能够读到这个修改的值oop

 

3.Synchronized与ReentranckLock区别

 

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

    2. Lock能够实现公平锁或不公平锁,而Synchronized是不公平的,并且永远都是不公平的。但 JVM 保证了全部线程最终都会获得它们所等候的锁,可是Lock做为默认设置,把公平设置为false 性能

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

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

 

4. 重要点线程

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

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)同步代码块对象

相关文章
相关标签/搜索