zoukankan      html  css  js  c++  java
  • 并发高级知识

    1.synchronized void f()

    2.使用Lock,更好的管理异常;尝试获取锁一段时间;

    private Lock lock = new ReentrantLock();
      public int next() {
        lock.lock();
        try {
          ++currentEvenValue;
          Thread.yield(); // Cause failure faster
          ++currentEvenValue;
          return currentEvenValue;
        } finally {
          lock.unlock();
        }

    尝试获取锁最终未获取锁:

    captured = lock.tryLock(2, TimeUnit.SECONDS);

    更细粒度的控制;

    3.volitail保证了可视性(尤其在多处理器系统)

    4.原子性变量类:AtomicInteger,AtomicLong,AtomicReference

    重要方法:

    public final boolean compareAndSet(int expect, int update) {
            return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
        }

    这是一个本地方法:

     public final native boolean compareAndSwapInt(Object obj, long l, int i, int j);

    在硬件层面保证了原子性

    5.临界区,也被称为同步代码块

     synchronized(this) {
          p.incrementX();
          p.incrementY();
          temp = getPair();
        }

    优点:相比同步方法,控制粒度更小,其他线程能更多地访问

    注意:synchronized块必须给定一个在其上进行同步的对象,最合理的方式是使用其方法正在被调用的当前对象,如果获得了synchronized块的锁,那么该对象其他的synchronized方法和临界区就不能被调用了

    6,线程本地存储:ThreadLocal

     private static ThreadLocal<Integer> value =
        new ThreadLocal<Integer>() {
          private Random rand = new Random(47);
          protected synchronized Integer initialValue() {
            return rand.nextInt(10000);
          }
        };
    public static void increment() {
        value.set(value.get() + 1);
      }

    注意,ThreadLocal并不是一个Map<Thread,value>,而是在当前Thread线程的一个成员变量:

    public void set(T value) {
            Thread t = Thread.currentThread();
            ThreadLocalMap map = getMap(t);
            if (map != null)
                map.set(this, value);
            else
                createMap(t, value);
        }
    ThreadLocal.ThreadLocalMap threadLocals = null;

    7.终结任务

    Thread.interrupt()

    Executor.shutdownNow()--interrupte它启动的所有线程

    中断某一个单一任务:

     Future<?> f = exec.submit(r);
        TimeUnit.MILLISECONDS.sleep(100);
        print("Interrupting " + r.getClass().getName());
        f.cancel(true); // Interrupts if running

    8.线程之间的协作:某些部分必须在其他部分被解决之前解决

    wait();

    notifyAll();唤醒等待这个锁的所有任务

    notify();只有一个等待这个锁的任务会被唤醒

    上面这三个方法都是Object类中的方法

    9.生产者-消费者与队列

    wait与notify可以进行生产者-消费者的模型构建,以一种低级的方式解决了任务互操作的问题,即每次交互时都握手。

    更高的抽象级别,是使用同步队列来解决任务协作问题,同步队列在任何时刻都只允许一个任务插入或移除元素。

    java.util.concurrent.BlockingQueue接口中提供了这个队列,通常可以使用无界队列LinkedBlockingQueue(通过使用ReentrantLock加锁),还可以使用ArrayBlockingQueue,它具有固定的尺寸。

    当队列为空时,可以自动挂起消费者任务,当队列中有元素时,可以自动恢复消费者任务,比起wait和notity,这种方式简单而可靠(消除了类之间的耦合)。

    一个烤面包的示例:

    class Toast {
      public enum Status { DRY, BUTTERED, JAMMED }
      private Status status = Status.DRY;
      private final int id;
      public Toast(int idn) { id = idn; }
      public void butter() { status = Status.BUTTERED; }
      public void jam() { status = Status.JAMMED; }
      public Status getStatus() { return status; }
      public int getId() { return id; }
      public String toString() {
        return "Toast " + id + ": " + status;
      }
    }
    
    class ToastQueue extends LinkedBlockingQueue<Toast> {}
    
    class Toaster implements Runnable {
      private ToastQueue toastQueue;
      private int count = 0;
      private Random rand = new Random(47);
      public Toaster(ToastQueue tq) { toastQueue = tq; }
      public void run() {
        try {
          while(!Thread.interrupted()) {
            TimeUnit.MILLISECONDS.sleep(
              100 + rand.nextInt(500));
            // Make toast
            Toast t = new Toast(count++);
            print(t);
            // Insert into queue
            toastQueue.put(t);
          }
        } catch(InterruptedException e) {
          print("Toaster interrupted");
        }
        print("Toaster off");
      }
    }
    
    // Apply butter to toast:
    class Butterer implements Runnable {
      private ToastQueue dryQueue, butteredQueue;
      public Butterer(ToastQueue dry, ToastQueue buttered) {
        dryQueue = dry;
        butteredQueue = buttered;
      }
      public void run() {
        try {
          while(!Thread.interrupted()) {
            // Blocks until next piece of toast is available:
            Toast t = dryQueue.take();
            t.butter();
            print(t);
            butteredQueue.put(t);
          }
        } catch(InterruptedException e) {
          print("Butterer interrupted");
        }
        print("Butterer off");
      }
    }
    
    // Apply jam to buttered toast:
    class Jammer implements Runnable {
      private ToastQueue butteredQueue, finishedQueue;
      public Jammer(ToastQueue buttered, ToastQueue finished) {
        butteredQueue = buttered;
        finishedQueue = finished;
      }
      public void run() {
        try {
          while(!Thread.interrupted()) {
            // Blocks until next piece of toast is available:
            Toast t = butteredQueue.take();
            t.jam();
            print(t);
            finishedQueue.put(t);
          }
        } catch(InterruptedException e) {
          print("Jammer interrupted");
        }
        print("Jammer off");
      }
    }
    
    // Consume the toast:
    class Eater implements Runnable {
      private ToastQueue finishedQueue;
      private int counter = 0;
      public Eater(ToastQueue finished) {
        finishedQueue = finished;
      }
      public void run() {
        try {
          while(!Thread.interrupted()) {
            // Blocks until next piece of toast is available:
            Toast t = finishedQueue.take();
            // Verify that the toast is coming in order,
            // and that all pieces are getting jammed:
            if(t.getId() != counter++ ||
               t.getStatus() != Toast.Status.JAMMED) {
              print(">>>> Error: " + t);
              System.exit(1);
            } else
              print("Chomp! " + t);
          }
        } catch(InterruptedException e) {
          print("Eater interrupted");
        }
        print("Eater off");
      }
    }
    
    public class ToastOMatic {
      public static void main(String[] args) throws Exception {
        ToastQueue dryQueue = new ToastQueue(),
                   butteredQueue = new ToastQueue(),
                   finishedQueue = new ToastQueue();
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(new Toaster(dryQueue));
        exec.execute(new Butterer(dryQueue, butteredQueue));
        exec.execute(new Jammer(butteredQueue, finishedQueue));
        exec.execute(new Eater(finishedQueue));
        TimeUnit.SECONDS.sleep(5);
        exec.shutdownNow();
      }
    }

    10.死锁

    必须同时满足4个条件:

    1.互斥条件:至少有一个资源不能共享

    2.至少有一个任务持有一个资源且等待别的资源

    3.资源不能被任务抢占

    4.必须有循环等待

    防止死锁,只需破坏其中一个即可,最容易的方法是破坏第四个条件

    11.CountDownLatch

    同步多个任务,CountDownLatch设置一个初始计数值,任务调用countDown()减小计数值,直到为0

    12.CyclicBarrier

    创建一组任务,当这组任务都完成时才能进行下一步

    13.DelayQueue

    是一种无界阻塞队列,其中的元素只有在到期时才能被取走

    14.PriorityBlockingQueue

    优先级队列

    15.免锁容器

    CopyOnWriteArrayList:对容器的修改和读取可以同时发生

    存储数组:

    private volatile transient Object[] array;//volatile保证可见性

    add方法:

    public boolean add(E e) {
            final ReentrantLock lock = this.lock;
            lock.lock();//使用锁
            try {
                Object[] elements = getArray();//获取旧的数据的副本
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len + 1);
                newElements[len] = e;
                setArray(newElements);//更新数据
                return true;
            } finally {
                lock.unlock();
            }
        }

    CopyOnWriteArraySet:借助CopyOnWriteArrayList实现免锁

    ConcurrentHashMap<K, V>:用桶粒度的锁,避免了put和get中对整个map的锁定,尤其在get中,只对一个HashEntry做锁定操作

    ConcurrentLinkedQueue

    16.乐观加锁:即原子类中的compareAndSet()方法

    17.ReadWriteLock:对经常读取的操作进行了优化,但是修改期间仍不能读取

  • 相关阅读:
    什么是电信BOSS系统?
    得到windows系统图标的解决方案
    FusionChart实现金字塔分布图
    OCP-1Z0-051-V9.02-91题
    FusionChart用XML和JSON两种格式提供数据源
    OCP-1Z0-051-V9.02-156题
    OCP-1Z0-051-V9.02-155题
    OCP-1Z0-051-V9.02-154题
    OCP-1Z0-051-V9.02-153题
    OCP-1Z0-051-V9.02-151题
  • 原文地址:https://www.cnblogs.com/qilong853/p/6515605.html
Copyright © 2011-2022 走看看