多线程、高并发(理解一)

进程、线程、纤程

进程:一个应用程序
线程:进程的最小执行单元
纤程:

创建线程的几种方式

static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println("Hello MyThread!");
        }
    }

    static class MyRun implements Runnable {
        @Override
        public void run() {
            System.out.println("Hello MyRunable!");
        }
    }

    static class MyCall implements Callable<String> {
        @Override
        public String call() {
            System.out.println("MyCall Callable!");
            return "success";
        }
    }

    public static void main(String[] args) {
        //继承thread类
        new MyThread().start();
        //实现runnable接口
        new Thread(new MyRun()).start();
        //lambda 表达式
        new Thread(()->{
            System.out.println("Hello Lambda!");
        }).start();
        
        //callable 
        Thread t=new Thread(new FutureTask<String>(new MyCall()));
        t.start();

        //线程池启动
        ExecutorService executorService= ç.newCachedThreadPool();
        executorService.execute(()->{
            System.out.println(" my Callable");
        });
        executorService.shutdown();
    }

synchronized

分别是无锁状态、偏向锁、轻量级锁和重量级锁
java中锁的四种状态
java中锁的四种状态

volatile

AtomicX

AtomicInteger

JUC 同步锁

ReentrantLock

Lock lock = new ReentrantLock();

CountDownLatch 倒数的门栓

CyclicBarrier 复杂操作完成,再走后续逻辑

参考:https://www.jianshu.com/p/128476015902

Phaser 所有线程需要在屏障上等待才能进入下一步执行

jdk 1.7 引入 

onAdvance方法是protected方法,子类可以覆写,该方法是最后一个到达的线程执行的,如果返回true表示需要终止Phaser,否则继续下一轮的phase,因此可以借助该方法实现CyclicBarrier的回调函数功能,也可以控制Phaser的阶段数,

我们可以将Phaser的概念看成是一个个的阶段, 每个阶段都需要执行的线程任务,任务执行完毕后就进入下一阶段。这里和CyclicBarrier 和CountDownLatch的概念类似, 实际上也确实可以用Phaser代替CyclicBarrier和CountDownLatch。

Phaser也是通过计数器来控制, 在Phaser中叫parties, 我们在指定了parties之后, Phaser可以根据需要动态增加或减少parties的值。

Phaser 是一个障碍,在继续执行之前需要等待动态数量的线程。在 CountDownLatch 中,该数字不能动态配置,需要在我们创建实例时提供。
public int register() //向此移相器添加一个新的未到达方。
 
public int bulkRegister(int parties)  // 将给定数量的新未到达方添加到此移相器。
 
public int arriveAndDeregister() // 到达此移相器并从其注销,而无需等待其他人到达
 
public int arrive()  // 到达此移相器,无需等待其他人到达
 
public int arriveAndAwaitAdvance()  // 到达这个移相器并等待其他人
 
public int awaitAdvance(int phase)  // 等待此移相器的相位从给定的相位值前进,如果当前相位不等于给定的相位值或此移相器终止,则立即返回。
 
public int awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit)  // 等待此移相器的相位从给定的相位值或给定的超时时间过去,InterruptedException如果在等待时中断则抛出,或者如果当前相位不等于给定的相位值或此移相器终止,则立即返回
 
public final int getPhase() // 返回当前阶段号
 
public int getRegisteredParties()  // 返回在此移相器上注册的参与方数量
 
public int getArrivedParties()  // 返回已到达此移相器当前阶段的已注册方的数量
 
public int getUnarrivedParties()  // 返回尚未到达此移相器当前阶段的已注册方的数量。 

ReadWriteLock

StampedLock相较于普通读写锁,增加了一种乐观读。
可重入读写锁的基本使用,该锁只能在单服务实例中使用,不适合分布式多服务实例集群; ?
ReadWriteLock维护一对关联的locks,一个用于只读操作,一个用于写操作。read lock可以由多个阅读器同时进行,只要没有作者 write lock 是独家的。

写锁不存在、多次加读锁成功
写锁存在、加读锁失败、加写锁失败
读锁不存在、单次加写锁成功、多次加写锁只有第一个写锁能成功
读锁存在、加读锁成功、加写锁失败

Semaphore

Semaphore是一种计数信号量,用于控制对共享资源的访问。它维护了一个内部计数器,表示可用的许可数量。线程可以通过获取许可来访问资源,并在使用完资源后释放许可。如果许可数量为0,则获取许可的线程将被阻塞,直到有其他线程释放许可为止。

Semaphore是Java并发编程中一个强大的工具,用于控制对共享资源的访问和实现线程之间的同步。与其他并发控制机制相比,Semaphore具有灵活性和可扩展性。选择Semaphore还是其他机制取决于具体的需求和场景。在使用Semaphore时,需要注意正确地获取和释放许可,以避免死锁和资源争用等问题。

Exchanger 线程间的通信

两个线程之间交换数据

LockSupport

AbstractQueuedSynchronizer 队列

(限流 Guava RateLimiter)

乐观锁与悲观锁

乐观锁与悲观锁的基本概念

何为乐观锁与悲观锁?

乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题。

乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。
因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。

悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。
因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。

乐观锁与悲观锁的实现方式

悲观锁的实现方式是加锁,加锁既可以是对代码块加锁(如Java的synchronized关键字),也可以是对数据加锁(如MySQL中的排它锁)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值