当前位置: 首页 > news >正文

商务网站建设论文sem竞价推广托管

商务网站建设论文,sem竞价推广托管,用python做的电商网站,做爰的视频网站一.线程安全的定义 线程安全是指在多线程环境下,对共享资源进行并发访问时,程序能够正确地处理,不会出现数据不一致、逻辑错误等问题,确保程序的执行结果与单线程环境下的执行结果相同,或者符合预期的并发逻辑。 有些代…

一.线程安全的定义

线程安全是指在多线程环境下,对共享资源进行并发访问时,程序能够正确地处理,不会出现数据不一致、逻辑错误等问题,确保程序的执行结果与单线程环境下的执行结果相同,或者符合预期的并发逻辑。

有些代码在多线程环境执行下会出现问题,这样的问题就称为线程不安全

二.synchronized 关键字

1.作用

核心特性

  • 互斥性:同一时间只有一个线程持有锁,其他线程阻塞等待。
  • 自动释放锁:退出同步块或方法时,锁自动释放。

synchronized 关键字在 Java 里用于实现同步机制,保证同一时刻只有一个线程可以访问被保护的代码块或方法。 

2.用法

1.修饰方法  2.修饰代码块 (必须指定锁对象!!)

// 同步方法
public synchronized void syncMethod() {// 操作共享资源
}// 同步代码块
public void syncBlock() {synchronized (lockObject) {// 操作共享资源}
}

三.什么是锁对象

1. synchronized 修饰静态方法

Counter 类的 increase 方法被 static synchronized 修饰,其锁对象是 Counter 类的 Class 对象,也就是 Counter.class。示例代码如下:

1.1示例代码

class Counter {// 将 count 定义为静态变量private static int count = 0;// 使用 synchronized 保证线程安全public static synchronized void increase() {count++;}public static int getCount() {return count;}
}class Demo {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {Counter.increase();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {Counter.increase();}});thread1.start();thread2.start();// 等待两个线程执行完毕thread1.join();thread2.join();// 打印计数器的结果System.out.println("最终计数结果: " + Counter.getCount());}
}

1.2 代码结果 

 代码结果:(因为所持有的锁对象为同一个) 

1.3 代码解释 

具体到你的代码,Counter 类的 increase 方法:

在多线程环境下,当一个线程进入 increase 方法时,它会尝试获取 Counter.class 这个锁对象。如果该锁对象当前没有被其他线程持有,那么这个线程就可以对这个锁对象进行加锁--执行 count++ 操作;在这个线程执行期间,其他线程如果也想进入 increase 方法,就会被阻塞,直到持有锁的线程执行完 increase 方法并释放 Counter.class 锁(对Counter.class这个锁对象进行解锁)。 

2. synchronized 修饰实例方法

若 synchronized 修饰的是实例方法,锁对象是调用该方法的实例对象(即 this)。示例如下:

2.1 示例代码

class Counter {public int count = 0;public synchronized void increase() {count++;}
}class Demo14 {private static Counter counter1 = new Counter();private static Counter counter2 = new Counter();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {counter1.increase();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {counter2.increase();}});t1.start();t2.start();t1.join();t2.join();// 修正输出,打印已定义的变量System.out.println("counter1 count: " + counter1.count);System.out.println("counter2 count: " + counter2.count);}
}

2.2 代码结果 

代码结果:(各自计数为 50000

2.3 代码解释 

此时的两个线程持有的锁对象不是同一个。线程t1,t2持有的锁对象是counter1,counter2变量指向的不同Counter对象

3. synchronized 修饰代码块

这里的this表示谁调用了increase()方法里面,synchroized修饰的代码块就针对谁进行加锁

此时的两个线程的锁对象为同一个——>counter变量指向的Counter对象

题外话:

static 修饰引用对象变量。首先,static 修饰的变量属于类,所有实例共享。示例里的 Counter counter 被 static 修饰,是类变量,整个类共享这一个实例

class Counter {public int count = 0;public void increase() {synchronized (this) {count++;}}
}class Demo14 {private static Counter counter = new Counter();public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {counter.increase();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {counter.increase();}});t1.start();t2.start();// 主线程等待子线程执行完毕t1.join(); t2.join(); System.out.println("输出结果:" + counter.count);}
}

综上所述,锁对象的选择取决于 synchronized 的使用方式,不同的锁对象会影响同步的范围和效果。

四.原子性问题

先来看一段问题代码

1. 问题代码

class Counter {// 将 count 定义为静态变量private static int count = 0;//increase定义为静态方法public static void increase() {count++;}public static int getCount() {return count;}
}class Demo {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {for (int i = 0; i < 5000; i++) {Counter.increase();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 5000; i++) {Counter.increase();}});thread1.start();thread2.start();// 等待两个线程执行完毕thread1.join();thread2.join();// 打印计数器的结果System.out.println("最终计数结果: " + Counter.getCount());}
}

1.1 运行结果

( 每次运行结果都不一样)

2.出现问题的原因

    接下来说明什么是原子性 

    2.1 什么是原子性?

    原子性指的是一个操作是不可中断的,要么全部执行,要么都不执行。在多线程环境下,如果多个线程同时修改共享变量,可能会导致数据不一致。比如 i++ 这样的操作,虽然看起来是一条语句,但实际上分为读取、增加和写入三个步骤,这就不是原子的。

    原子性问题源于 CPU 指令的非原子性。例如,i++ 看似是一条语句,但实际分为三步:

    1. 读取:从内存读取变量 i 的值。
    2. 增加:在 CPU 寄存*器中执行 +1 操作。
    3. 写入:将结果写回内存。

    2.2 问题代码解释


    count++ 操作并非原子操作,其底层执行分为 “读取值 → 计算新值 → 写入值” 三个步骤。多线程环境下,若多个线程同时执行 count++,可能出现以下场景:

    1. 线程 A 读取 count 值为 10,还未执行写入;
    2. 线程 B 也读取 count 值为 10(此时线程 A 的修改未生效);
    3. 线程 A、B 分别计算新值为 11 并写入。最终 count 只增加了 1,而非预期的增加 2,导致计数丢失。

    3.解决方案

    跳转到———目录1.二.三

    五.内存可见性问题

    • 每个线程有自己的工作内存(缓存),共享变量存储在主内存中。
    • 线程操作变量时需先将变量从主内存复制到工作内存,修改后再写回主内存。
    • 示例:线程 A 修改主内存中的变量 x,若未及时写回,线程 B 的工作内存中仍保留旧值 x=0,导致可见性问题。

    1. 问题代码 

    public class VisibilityProblem {private static boolean flag = false;public static void main(String[] args) throws InterruptedException {// 修改线程:500ms后修改flag为truenew Thread(() -> {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}flag = true;System.out.println("修改线程:flag已设为true");}).start();// 读取线程:循环检查flagnew Thread(() -> {while (!flag) {// 空循环,等待flag变为true}System.out.println("读取线程:接收到flag为true");}).start();}
    }

    1.1 预期输出

    修改线程:flag已设为true

    读取线程:接收到flag为true

    1.2 实际输出

    修改线程:flag已设为true (程序不终止,读取线程无法感知flag的修改)

    2. 问题原因

    • 读取线程的工作内存(缓存)读取的是 flag 的旧值(false),未从主内存更新,导致循环无法终止

    3.解决办法

    1.使用volatile 关键字

    原理

    • volatile 强制读取线程每次从主内存获取 flag 的最新值,确保可见性。

    修改后的代码 

     private static volatile boolean flag = false; // 添加volatile关键字

     2.使用 synchronized

    原理

    • synchronized 保证同一时间只有一个线程操作 flag,且退出同步块时强制将 flag 写回主内存,确保可见性。

    修改后的代码

    public class VisibilityProblem {private static boolean flag = false;// 静态锁对象(所有线程共享同一把锁)private static final Object LOCK = new Object();public static void main(String[] args) throws InterruptedException {// 修改线程:500ms后修改flag为truenew Thread(() -> {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}synchronized (LOCK) { // 获取锁flag = true;System.out.println("修改线程:flag已设为true");}}).start();// 读取线程:循环检查flagnew Thread(() -> {while (true) { // 死循环+锁内检查synchronized (LOCK) { // 获取同一把锁if (flag) { // 锁内读取,保证可见性System.out.println("读取线程:接收到flag为true");break; // 退出循环}}// 锁外可添加短暂休眠避免空转(非必须)// Thread.yield();}}).start();}
    }

     3.两者区别

    • 简单场景用 volatile,保证可见性。但不保证原子性
    • 复杂场景用 synchronized 或 Lock,同时保证原子性和可见性。

    六.抢占式执行问题

    1.作用

    waitnotifyObject类的两个重要方法,用于实现线程间的通信与协作(调度线程执行顺序),它们通常和synchronized关键字配合使用

     2.wait和notify和notifyAll

    1.wait():使当前线程进入等待状态,同时释放该线程持有的对象锁。线程会进入等待队列 ,直到其他线程调用同一对象的notify()notifyAll()方法将其唤醒

    2.notify()唤醒等待在同一对象上的一个线程。被唤醒的线程不会立即执行,而是进入阻塞队列,等待调用notify()的线程释放锁之后,再重新竞争锁,获取到锁后才能继续执行。

    3.notifyAll()唤醒等待在同一对象上的所有线程。这些被唤醒的线程同样会进入阻塞队列竞争锁。通常情况下,为避免某些线程长时间处于等待状态导致死锁,推荐使用notifyAll()

    .使用注意事项 

    • 必须在同步块或同步方法中调用waitnotify方法必须在synchronized修饰的代码块或方法中使用。因为它们依赖于对象的监视器锁(monitor),只有持有该对象锁的线程才能调用这两个方法,否则会抛出IllegalMonitorStateException异常。
    • 调用线程需持有对象锁:当线程调用wait方法时,它必须已经持有该对象的锁;同样,调用notifynotifyAll方法的线程也需要持有对象锁。

    3. 极简案例:

    《两个线程交替打印数字和字母(5 轮)》:

    public class SimpleAlternatePrint {private static final Object LOCK = new Object();private static int turn = 0; // 0=数字线程,1=字母线程public static void main(String[] args) {// 数字线程(打印1-5)new Thread(() -> {for (int i = 1; i <= 5; i++) {synchronized (LOCK) {while (turn != 0) { // 不是自己的回合,等待try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); }}System.out.print(i + " "); // 打印数字turn = 1; // 切换回合LOCK.notify(); // 唤醒字母线程}}}).start();// 字母线程(打印A-E)new Thread(() -> {for (char c = 'A'; c <= 'E'; c++) {synchronized (LOCK) {while (turn != 1) { // 不是自己的回合,等待try { LOCK.wait(); } catch (InterruptedException e) { e.printStackTrace(); }}System.out.print(c + " "); // 打印字母turn = 0; // 切换回合LOCK.notify(); // 唤醒数字线程}}}).start();}
    }

    4.复杂案例

    《三个线程按顺序执行任务》:

    class ThreadSequence {private boolean isFirstDone = false;private boolean isSecondDone = false;// 第一个线程执行的方法public synchronized void firstTask() throws InterruptedException {System.out.println("First task started");// 模拟任务执行Thread.sleep(1000);System.out.println("First task completed");//把isFirstDone标志为true,第二个线程结束等待循环了,开始进入下一任务isFirstDone = true;notifyAll();// 1.唤醒等待在同一个对象上的所有线程 //2.第一个线程释放锁}// 第二个线程执行的方法public synchronized void secondTask() throws InterruptedException {while (!isFirstDone) {// 等待第一个线程完成wait();}System.out.println("Second task started");// 模拟任务执行Thread.sleep(1000);System.out.println("Second task completed");isSecondDone = true;// 唤醒等待的第三个线程notifyAll();}// 第三个线程执行的方法public synchronized void thirdTask() throws InterruptedException {while (!isSecondDone) {// 等待第二个线程完成wait();}System.out.println("Third task started");// 模拟任务执行Thread.sleep(1000);System.out.println("Third task completed");}
    }

    4.1 运行结果

    4.2 运行顺序说明 

    1. First 线程执行 firstTask

    • 持有锁 → 打印First task started → 睡眠 1 秒 → 打印First task completed → 设置isFirstDone=true → 调用notifyAll()

    • 关键:唤醒所有等待在ThreadSequence对象上的线程(包括 Second、Third 线程),但此时 Second/Third 尚未进入等待状态(因未获取锁)。

    2. Second 线程执行 secondTask

    • 竞争锁 → 进入循环:while (!isFirstDone) → 第一次检查isFirstDone=false → 调用wait() → 释放锁,进入等待队列

    • 等待:直到 First 线程调用notifyAll()后,Second 线程被唤醒 → 重新竞争锁 → 检查isFirstDone=true → 退出循环

    • 执行:打印Second task started → 睡眠 1 秒 → 打印Second task completed → 设置isSecondDone=true → 调用notifyAll()

    3. Third 线程执行 thirdTask

    • 竞争锁 → 进入循环:while (!isSecondDone) → 第一次检查isSecondDone=false → 调用wait() → 释放锁,进入等待队列

    • 等待:直到 Second 线程调用notifyAll()后,Third 线程被唤醒 → 重新竞争锁 → 检查isSecondDone=true → 退出循环

    • 执行:打印Third task started → 睡眠 1 秒 → 打印Third task completed

    http://www.cadmedia.cn/news/11192.html

    相关文章:

  1. 昆明app开发公司网站建设seo优化培训
  2. 网站免费建站性盈盈影院windows优化大师下载
  3. 网站建设的域名北京seo薪资
  4. 电力建设科学技术进步申报网站百度竞价排名广告定价
  5. 武汉网站建设哪家强每日国际新闻最新消息
  6. 网站建设放什么会计科目国外搜索引擎
  7. 海口网站建设呢网络热词有哪些
  8. 九江 网站建设公司2022最近比较火的热点话题
  9. 网站群建设意见征集郑州网络推广
  10. 哔哩哔哩推广网站优化教程网下载
  11. 网站建设平台赚钱线上营销手段
  12. 商场设计与商品陈列苏州seo排名公司
  13. 北京企业网站建设方案成品网站1688入口的功能介绍
  14. 网站建设上机考试题目谷歌seo顾问
  15. 企业网站的基本形式不包括优化软件seo排名
  16. 大连网站seo顾问百度收录站长工具
  17. 佛山市住房建设局网站恢复2345网址导航
  18. 做网站哪个公司最专业的google推广公司
  19. 网站建设 9a微信管理工具
  20. 兰溪优秀高端网站设计地址如何推广一款app
  21. 锋创科技园网站建设网络营销顾问是做什么的
  22. 怎样防止网站被黑潍坊快速网站排名
  23. 淘宝加盟网站建设b站推广入口2023破解版
  24. 课程网站建设简介百度知道客服
  25. 网站建设怎么上传数据经典营销案例分析
  26. 河北注册公司流程和费用惠州seo排名外包
  27. 雅安建设网站谷歌商店app下载
  28. 网站建设怎么添加评论外链网盘网站
  29. 成都市四方建设工程监理有限公司网站免费建网站最新视频教程
  30. 酒店网站建设功能上海优化营商环境