• java并发编程[持续更新]


    [toc]

    java并发编程

    1.常用类介绍

    Semaphore

    Semaphore 类是一个计数信号量,必须由获取它的线程释放, 通常用于限制可以访问某些资源(物理或逻辑的)线程数目。

    Semaphore包含三种操作

    1. 初始化

    2. 获取acquire()

    3. 释放 release()

    当信号量大于0的时候semaphore会响应线程请求,释放资源,当信号量等于0时即阻塞线程。

    Semaphore有两种模式,公平模式和非公平模式

    公平模式遵循FIFO,按照acquire的顺序来分配资源,非公平则为抢占式的。

    Semaphore的类图如下,使用内部类Sync继承AbstractQueuedSynchronizer实现

    classDiagram Serializable <|-- Semaphore : implements Semaphore *-- Sync AbstractQueuedSynchronizer <|-- Sync Sync <|-- NonfairSync Sync <|-- FairSync class Semaphore{ Semaphore : -Sync sync Semaphore: +Semaphore(int permits) Semaphore: +Semaphore(int permits, boolean fair) Semaphore: +acquire() Semaphore: +acquire(int permits) Semaphore: +release() Semaphore: +release(int permits) } class Sync{ ... } class NonfairSync{ ... } class FairSync{ ... }

    2.名词解释

    2.1 线程安全

    如果一个进程中有多个线程在同时运行同一段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

    2.2 可重入锁和不可重入锁

    可重入锁,指的是以线程为单位,当一个线程获取对象锁之后,这个线程可以再次获取本对象上的锁,而其他的线程是不可以的。意义之一在于防止死锁*。

    实现原理:每个锁关联一个请求计数器和占有他的线程,当计数为0时,锁未被占用,当线程请求占用锁时,jvm标记锁的占有者,且将请求计数器置为1。同一线程再次请求锁,计数器递增。每当占用线程退出同步块,计数器递减,知道计数器为0,锁被释放。

    *:此处的防止死锁实例

    public class demo {
        public synchronized void methodA(){
            methodB();
        }
    
        public synchronized void methodB(){
            //todo do something
        }
    }
    

    当一个线程调用demo类对象的methodA同步方法,如果demo类对象锁未被占有,该线程占有锁,此时调用methodA会触发methodB的调用,此时需要再获取一次锁,只有可重入可以实现。

    如下,子类覆写了父类的synchonized方法,然后调用父类中的方法,此时如果没有可重入的锁,那么这段代码将产生死锁

    public class Demo {
        int i = 10;
    
        public synchronized void parent() {
            i--;
            System.out.println("parent:" + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        static class Demo2 extends Demo {
            @Override
            public synchronized void parent() {
                try {
                    while (i > 1) {
                        i--;
                        System.out.println("child:" + i);
                        Thread.sleep(100);
                        super.parent();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    Demo2 demo2 = new Demo2();
                    demo2.parent();
                }
            });
            thread.start();
        }
    }
    

    synchronized和ReentrantLock都是可重入锁

  • 相关阅读:
    WPF 进度条
    WPF CPU使用率线性表
    Android annotation
    git 操作
    git 合并指定目录到master
    远程连接mysql报错,ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' (using password: NO)解决方案
    centos7 安装python2.7.14 并与原版本共存
    pycahrm 断点调试
    ImportError: No module named Crypto.Cipher 报错解决方法
    python操作 rabbitMQ
  • 原文地址:https://www.cnblogs.com/CodingJacob/p/12172381.html
Copyright © 2020-2023  润新知