季纯卿
前言
hello,大家好!这里季纯卿 ,别来无恙
Java基础专栏点击
今天接上一章开始学习:
线程同步和线程不同步
基本数据类型
线程同步:同一时间只有一个执行
- 线程安全的场景
- 数据是安全的,但是处理效率会低一些
数据不同步:很有可以capy为同一个值,(多个线程同时在操作一个对象)
- 线程不安全的场景
- 数据是不安全的,但是处理效率会高一些
- 线程不安全有的时候可以容忍(因为同步,按照一条一条的处理,违背了多线程)
线程安全:执行效率低一些
线程不安全:执行效率高一些
线程锁
想要线程处理速度高一点,然后数据尽可能安全,这个时候就可以用到线程之间的锁
锁就是让原来不同步的模式,短暂变得同步
目的:就是为了处理线程不安全,导致数据不一致的问题,
在需要的时候同步,不需要不同步
(在某一个场景类,需要)
比如在下列代码释放中只需要在count++的时候同步,其他的时候都不需要同步
确保这个count出来的数据他是一个正确的数据
线程一个一个的修改,才能保证线程安全
1. AQS(Abstract Queued Synchronizer)抽象队列同步
Java中的同步器的框架
这个同步器类里面定义了:如何去对线程加锁
1.2 实现类
CountDownLatch(倒计时锁)
ReentrantLock(重入锁) [ 用的最多 ]
ReentrantReadwriteLock(可重入写锁)
Semaphore(信号灯)
1.3 可重入的互斥锁 - ReentrantLock
(一个线程你在等待的时候,CPU就不会管你 了,会把资源释放给其他的任务进行处理)
默认情况下:采用的非公平模式
解锁
一旦调用lock()方法加锁,就一个要调用unlock()解锁
如果没有解锁就会把后面所有的线程锁死,这是一个很严重的问题
1.3.1 可重入
举个例子:我们在门上装了一把锁,这个时候有三个人走过来了,此时三个人同时抓住了这个门把手,但是钥匙孔只有一个。那么先拿钥匙开门的这个人,他就可以先开门走。另外两个人也想开门但是他们要等着别人,但是你等着别人在Java的执行过程当中,就会有一个情景发生,一个线程在等的过程当中,CPU就不会管你 了,会把资源释放给其他的任务进行处理。
这个时候第一个人开完门已经走路,走了之后,基于排队的机制已经有两个人抓找门把手上面了,他们只需要拿钥匙开门。第一个人处理完了,后面的两个人也要处理。
什么叫做可重入呢?就是这两个人再次进来的时候可以直接拿钥匙开门,就是他再次进来的时候,恢复到最后一次阻塞的位置。
1.3.2 不可重入
举个例子:就是三个人同时抓住这个门把手,只用一个人抢到了这个钥匙孔开门去了
不可重入概念就是:当这个人抢到了这个钥匙孔去开门的一刹那,抓着门把手的着两个就都会被踢除,之后他们就又要先去抢门把手才能开门
1.4 互斥锁
只要一个人抢到了锁,另外一个人就别想抢了
- 只能有一个线程访问被保护的资源
锁的定义在Lock里面
1.5 共享锁
大家都可以使用同一个把锁(允许多个线程共同访问资源)
也就是上面可重用的概念
1.6 公平锁:
就是所有人一个一个的依次去处理
1.7 非公平锁
先抢这个,没抢到,也要去抢
读锁
解锁
& - [ 代码 ] 锁的实现
public class CounterRun implements Runnable {
private static int count = 0;
private static int count1 = 0;
ReentrantLock lock = new ReentrantLock();//1-
// CountDownLatch counter = new CountDownLatch(200);
// Semaphore semaphore = new Semaphore(200);
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
SynchronizedText s = new SynchronizedText();
s.start();
}
}
@Override
public void run() {
counter();
sayHello();
}
//同步方法
public synchronized void sayHello() {
count++;
System.out.println("count0:" + count);
}
public void counter() {
/* counter.await();
counter.countDown();
semaphore.acquire();
semaphore.release();*/
lock.lock();//加锁 ReentrantLock 一旦加锁,必须手动释放unlock
count1++;
lock.unlock();//解锁
System.out.println("count1:" + count1);
}
public static int getCount() {
return count;
}
public static void setCount(int count) {
CounterRun.count = count;
}
public static int getCount1() {
return count1;
}
public static void setCount1(int count1) {
CounterRun.count1 = count1;
}
}
public class synchronizedText {
public static void main(String[] args)
{
CounterRun cr = new CounterRun();
for (int i = 0; i < 1000 ; i++)
{
Thread s = new Thread(cr);
Thread s1 = new Thread(cr);
Thread s2 = new Thread(cr);
Thread s3 = new Thread(cr);
Thread s4 = new Thread(cr);
s.start();
s1.start();
s2.start();
s3.start();
s4.start();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(CounterRun.getCount()+"=="+CounterRun.getCount1());
}
}
本节学习结束啦✿✿ヽ(°▽°)ノ✿
有什么问题欢迎大家提出来,一起进步
世界灿烂盛大,欢迎回家 —— 《全球高考》
本文由季纯卿讲解线程同步与线程不同步的概念,强调线程安全与效率的权衡。介绍了AQS(AbstractQueuedSynchronizer)作为同步器框架,及其实现类如ReentrantLock、CountDownLatch等。重点讨论了可重入锁ReentrantLock的原理和使用,包括公平锁与非公平锁的区别,并通过代码示例展示了ReentrantLock的加锁与解锁操作。
748

被折叠的 条评论
为什么被折叠?



