线程同步的概念_线程同步和异步的区别

线程同步的概念_线程同步和异步的区别常见线程同步的三种方式一:什么是线程同步线程同步是指两个或多个线程协同步调,按预期的顺序执行代码。1:若两个或多个线程同时访问同一个共享资源时,需要让多个线程之间按照顺序访问。2:若线程A

常见线程同步的三种方式   一:什么是线程同步   线程同步是指两个或多个线程协同步调,按预期的顺序执行代码。   1:若两个或多个线程同时访问同一个共享资源时,需要让多个线程之间按照顺序访问。   2:若线程A的执行依赖线程B的结果,需要依赖线程同步来保证两个线程的执行的顺序。   二:实现线程同步的几种方式   (一):synchronized   1:synchronized作用有三:               (1):保证程序执行的原子性   在多线程环境下,线程是CPU调度的基本单位,CPU根据不同的调度算法进行线程换。当一个线程获得时间片后开始执行,在时间片耗尽之后,就会失去CPU使用权。因此,在多线程场景下,由于时间片切换的原因,原子性问题可能会出现。   例如,线程1获得时间片开始执行,但在执行过程中,CPU时间片耗尽,线程1需要让出CPU。这时线程2获得了时间片开始执行。然而,对于线程1而言,它的操作可能并没有完全执行完成,也没有完全不执行,这就是原子性问题的产生。因此,保证原子性是非常重要的。   synchronized是如何保证程序执行的原子性呢?   通过 JDK 自带的  命令查看  类的相关字节码信息:首先切换到类的对应目录执行  命令生成编译后的 .class 文件,然后执行。     
线程同步的概念_线程同步和异步的区别   从图中可以看出:   同步语句块的实现使用的是  和  指令,其中  指令指向同步代码块的开始位置,  指令则指明同步代码块的结束位置。   在执行时,会尝试对象的锁,如果锁的计数器为 0 则表示锁可以被,后将锁计数器设为 1 也就是加 1。   在执行  指令后,将锁计数器设为 0,表明锁被释放。如果对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。   在锁未释放之前,其他线程无法再次锁,因此通过monitorenter和monitorexit指令可以保证被synchronized修饰的代码在同一时间只能被一个线程访问,其他线程在锁未释放之前无法访问该代码块。这样,synchronized可以保证方法和代码块内的操作是原子性的。   当线程执行monitorenter指令时,会对Monitor进行加锁,其他线程无法锁,除非线程主动解锁。即使在执行过程中,例如CPU时间片用完,线程放弃了CPU,但是并没有进行解锁。由于synchronized的锁是可重入的,线程在下一个时间片中仍然能够到锁,并继续执行代码,直到所有代码执行完毕。这样就保证了原子性。              (2):保证可见性   可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看到修改的值。   在Java内存模型中,所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中使用到的变量的主内存副本拷贝。线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。   不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递需要通过主内存进行数据同步。因此,就可能出现一个线程修改了某个变量的值,但是其他线程无法立即看到修改的值的情况。   为了保证可见性,使用synchronized关键字修饰的代码会在开始执行时加锁,在执行完成后解锁。根据可见性的规则,对一个变量解锁之前,必须先把此变量的值同步回主内存中。这样解锁后,后续的线程就可以访问到被修改后的值。因此,通过synchronized关键字锁住的对象,其值具有可见性。              (3):保证有序性   有性问题可以理解为在多线程环境下,一个线程中的操作可能会被重排或者乱序执行,而在另一个线程中观察这些操作的顺序可能是无法确定的。   Java允许编译器和处理器对指令进行重排,但是指令重排并不会影响单线程的顺序,它影响的是多线程并发执行的顺序性。synchronized保证了每个时刻都只有一个线程访问同步代码块,也就确定了线程执行同步代码块是分先后顺序的,保证了有序性。                 2:synchronized作为java的关键字,可以作用在代码块、实例方法、静态方法、和类。               (1):修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得 当前对象实例的锁   
线程同步的概念_线程同步和异步的区别   synchronized修饰的方法并没有monitorenter指令和monitorexit指令,取得代之的确实是ACC_SYNCHRONIZED标识,该标识指明了该方法是一个同步方法。JVM 通过该ACC_SYNCHRONIZED访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。                 (2):修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁。因为静态成员不属于任何一个实例对象,是类成员( static 表明这是该类的一个静态资源,不管 new 了多少个对象,只有一份)。所以,如果一个线程 A 调用一个实例对象的非静态  方法,而线程 B 需要调用这个实例对象所属类的静态  方法,是允许的,不会发生互斥现象,因为访问静态  方法占用的锁是当前类的锁,而访问非静态  方法占用的锁是当前实例对象锁。   (3):修饰代码块   指定加锁对象,对给定对象/类加锁。 表示进入同步代码库前要获得给定对象的锁。 表示进入同步代码前要获得 当前 class 的锁   (二):ReentrantLock   ReentranLock是一个支持重入的独占锁,在JUC(java.util.concurrent)包中,底层就是基于AQS实现的。   ReentranLock类本身并没有直接继承AQS(AbstractQueuedSynchronizer),而是创建了一个内部类Sync来继承了AQS,而ReentrantLock类本身的那些方法都是调用Sync里面的方法来实现,而Sync本身自己也是一个抽象类,它还有两个子类,分别是NonfairSync和FairSync,对锁各种实际的实现其实在这两个类中实现,顾名思义,这两个类分别实现了非公平锁和公平锁,在创建ReentrantLock时可以进行选择。   1:lock()   当定义为非公平锁时,先试用的方式更新中的的状态,默认是0代表没有被,当前线程就可以锁,然后把改为1,接着把当前线程标记为持有锁的线程,如果中的操作失败就表示锁已经被持有了,就会调用方法   当定义为公平锁,在子类FairSync中重写了tryAcquire方法,注意判断中的代码,也就是线程抢夺锁的时候会调用方法,这个方法会判断队列中有没有已经先等待的线程了,如果有则当前线程不会抢到锁,这就实现了公平性,上面方法则没有这种判断,所以后来的线程可能会比先等待的线程先拿到锁。   2:tryLock()   可以看到tryLock实际上是非公平锁的实现,不能保证正在排队的线程能拿到锁,因为可能被新来的线程抢走。   3:unlock()   这个方法是释放锁,最终会调用到类中的方法。在这个方法里面会对减1,如果减1之后为0就表示当前线程持有次数彻底清空了,需要释放锁。   (三):CountDownLatch   CountDownLatch中count down是倒数的意思,latch则是门闩的含义。整体含义可以理解为倒数的门栓,似乎有一点“三二一,芝麻开门”的感觉。   CountDownLatch的作用也是如此,在构造CountDownLatch(int count):的时候需要传入一个整数count,在这个整数“倒数”到0之前,主线程需要等待在门口,而这个“倒数”过程则是由各个执行线程驱动的,每个线程执行完一个任务“倒数”一次。   总结来说,CountDownLatch的作用就是等待其他的线程都执行完任务,必要时可以对各个任务的执行结果进行汇总,然后主线程才继续往下执行。   1:CountDownLatch(int count):构造方法,创建一个新的 CountDownLatch 实例,用给定的计数初始化。参数 count 表示线程需要等待的任务数量。   2:void await():使当前线程等待,直到计数器值变为0,除非线程被 interrupted。如果计数器的值已经为0,则此方法立即返回。在实际应用中,通常在主线程中调用此方法,等待其他子线程完成任务。   3:boolean await(long timeout, TimeUnit unit):使当前线程等待,直到计数器值变为0,或者指定的等待时间已到,或者线程被 interrupted。如果计数器的值已经为0,则此方法立即返回。   参数 timeout 是指定的等待时间,   参数 unit 是 timeout 的单位(如秒、毫秒等)。   此方法返回一个布尔值,表示在等待时间内计数器是否变为0。   4:void countDown():递减计数器的值。如果计数器的结果为0, 则释放所有等待的线程。在实际应用中,通常在线程完成任务后调用此方法。   5:long getCount():当前计数的值。返回当前 CountDownLatch 实例内部的计数值。   6:利用CountDownLatch实现ABC的的顺序打印

2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/60800.html

(0)
上一篇 2024年 8月 29日 下午3:47
下一篇 2024年 8月 29日

相关推荐

关注微信