day37 线程

一、线程安全

二、多线程并发的安全问题

当多个线程并发操作同一临界资源 由于线程切换实际不确定 导致操作顺序出现混乱

产生的程序bug 严重时出现系统瘫痪

临界资源 :操作该资源的完整流程同一时间只能被单一线程操作的资源  

 多线程并发会出现的各种问题、

       如图会出现的各种异常问题

        1. 数组长度不够
        2. 数组下标越界
        3. 0元素过多

两个线程可能会同时读取和修改c.array的长度,从而导致数组长度不一致,进而导致越界异常。在第一个线程使用Arrays.copyOf方法增加数组长度时,第二个线程可能会在此同时读取数组长度,然后在第一个线程修改完成之前,第二个线程又对数组进行了操作,从而导致长度不一致,然后就会出现越界异常。

public class Test {public static void main(String[] args) throws InterruptedException {Coo c = new Coo();Thread t1 = new Thread() {@Overridepublic void run() {synchronized (c){// System.out.println("this1:"+this);for (int i = 0; i < 100; i++) {c.array = Arrays.copyOf(c.array, c.array.length + 1);c.array[c.array.length-1] = i;}}}};Thread t2 = new Thread() {@Overridepublic void run() {synchronized (c){// System.out.println("this:"+this);for (int i = 100; i < 200; i++) {c.array = Arrays.copyOf(c.array, c.array.length + 1);c.array[c.array.length-1] = i;}}}};t1.start();t2.start();/*** 多执行几次,检查程序可能存在的问题,并尝试分析为什么会出现这些情况,以及解决方案**  1. 数组长度不够*  2. 数组下标越界*  3. 0元素过多*///Thread.sleep(1000); //阻塞1秒钟,等待上面两个线程干完活再输出t1.join();t2.join();System.out.println(c.array.length);System.out.println(Arrays.toString(c.array));}
}

 

当一个方法使用synchronized修饰 ,这个方法称之为同步方法,多个线程不能同时在方法内部执行

同步异步的区别 总结来说,同步和异步的区别:请求发出后,是否需要等待结果,才能继续执行其他操作

同步代码块使用的时候需要注意的是同步监视器对象的选择(重点)

1:对象可以是引用数据类型的对象

2:必须保证多个线程看到的对象是同一个

3:在方法上使用synchronized ,那么同步监视器对象就是this,不能自行指定,是默认的

 4: 静态方法上若使用synchronized,则该方法一定具有同步效果
 5注意:静态方法上执行的同步监视器对象不能使用this,而是当前类的类对象

 静态方法中使用同步代码块的锁对象应当是当前类的对象,格式:类名.class
 

 * 类对象:
 *  Class类的一个实例,JVM加载一个类的时候就会实例化一个Class的实例并用于保存加载这个类的
 *  相关信息,因此每个被加载的类都是有且仅有一个Class的实例与之对应,静态方法的锁对象就是它
 *  类对象会在后续的反射知识中详细说明

有限的缩小同步范围可以在保证并发安全的前提下保证效率

互斥锁

当使用多个Synchronized锁定多个代码片段 并且指定的所的对象相同时 这些代码片段就是互斥的

多个线程不能同时调用他们

package com.oracle.day37;public class SynchronizedDemo4 {public static void main(String[] args) {Doo d = new Doo();//    Thread t1 = new Thread(() -> d.methodA());Thread t1 = new Thread(){@Overridepublic void run() {d.methodA();d.methodB();}};
//    Thread t2 = new Thread(() -> d.methodB());Thread t2 = new Thread(){@Overridepublic void run() {d.methodA();d.methodB();}};t1.start();t2.start();}
}
class Doo{public synchronized void methodA()  {Thread t = Thread.currentThread();System.out.println(t.getName()+"正在执行方法A");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t.getName()+"方法A执行完毕");}public static void methodB() {Thread t = Thread.currentThread();System.out.println(t.getName()+"正在执行方法B");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t.getName()+"方法B执行完毕");}
}

死锁

在没有释放一把锁的同时调用了另一把锁   

锁中放锁

线程的通讯

每一个线程都是独立运行的状态 但需要多个线程完成同一件事

需要多个线程有规律地运行

线程之间就需要通信,告知对方自己的状态

概念 等待队列 唤醒

相关方法:

 void join()线程进入等待状态 等待另一条线程执行完毕然后继续执行

void wait()释放锁标记,进入等待队列

void wait(long time)释放锁 进入等待队列等待多长时间

void notify()唤醒线程

void notifyAll()唤醒全部线程

package com.oracle.day37.thread;public class ThreadDemo2 {public static Object o = new Object();public static void main(String[] args) {Thread t1 = new Thread(){@Overridepublic void run() {synchronized(o){for (int i = 1; i <= 26; i++) {System.out.println(i);try {o.wait();} catch (InterruptedException e) {e.printStackTrace();}o.notify();}}}};Thread t2 = new Thread(){@Overridepublic void run() {synchronized (o){for (int i = 'A'; i <= 'Z'; i++) {System.out.println((char)i);o.notify();try {o.wait();} catch (InterruptedException e) {e.printStackTrace();}}}}};t1.start();t2.start();}
}

锁的几种形式 

①:方法中添加synchronized修饰符

②:使用同步代码块

        synchronized(){};

* synchronized()可以添加
* this
* Object o
* Shop.class
* "abc"

③:Lock接口

要使用Lock接口,必须在线程中创建并获得Lock对象,然后在需要进行线程同步的代码块中使用lock()方法获取锁,使用unlock()方法释放锁。在多线程环境下,每个线程都必须单独创建自己的Lock对象,并进行锁定和解锁。这种方式可以保证每个线程都能够获取到自己的锁,从而在并发访问时保证线程安全性。

class BuyTicketMethod extends Thread{private static Integer M = 20;private final Lock lock = new ReentrantLock();@Overridepublic  void run() {for (int i = 0; i < 10; i++) {lock.lock();try {if (M > 0){System.out.println("您在"+Thread.currentThread().getName()+"购买成功剩余票是"+(--M)+"张");}} finally {lock.unlock();}}}
}

线程状态(线程的生命周期)

1创建状态:new Thread()对象

2就绪状态:线程对象.start(),线程等待cpu随机分配时间片长度

3运行状态:cpu随机分配给线程执行的cpu时间片

4阻塞状态:暂时让出cpu资源

5死亡状态

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/129741.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Serverless Framework 亚马逊云(AWS)中国地区部署指南

Serverless Framework 亚马逊云(AWS)中国地区部署指南 Serverless Framework 亚马逊云(AWS)中国地区部署指南 前言前置准备 1. 账号的注册2. 全局安装 serverless3. 设置你的系统环境变量4. 设置部署凭证 快速部署一个 hello world 创建入口函数 index.js event 参数context 参…

推荐一款新的自动化测试框架:DrissionPage

今天给大家推荐一款基于Python的网页自动化工具&#xff1a;DrissionPage。这款工具既能控制浏览器&#xff0c;也能收发数据包&#xff0c;甚至能把两者合而为一&#xff0c;简单来说&#xff1a;集合了WEB浏览器自动化的便利性和 requests 的高效率优点。 一、DrissionPage框…

查看创建好的数据库

MySQL从小白到总裁完整教程目录:https://blog.csdn.net/weixin_67859959/article/details/129334507?spm1001.2014.3001.5502 语法格式: show create database 数据库名称; 案列:查看testing数据库信息 mysql> show create database testing; ------------------------…

4.2 Ioc容器加载过程-Bean的生命周期深度剖析

Bean生命周期详解 第一步拿到父类BeanFactory子类 第二步&#xff0c;读取配置类 AnnotatedBeanDefinitionReader 用来读取配置类之外和还做了 第一个是解析类的处理器&#xff0c;没有的话我们的配置类就无法解析 总结this()无参构造函数里面实现了【三大步】 实例…

vue制作页面水印

1.新建一个js js的代码 let watermark {}let setWatermark (str) > {let id 1.23452384164.123412415if (document.getElementById(id) ! null) {document.body.removeChild(document.getElementById(id))}let can document.createElement(canvas)can.width 500can.he…

《TCP/IP网络编程》阅读笔记--并发多进程服务端的使用

目录 1--并发服务器端 2--进程 2-1--进程的相关概念 2-2--fork()创建进程 2-3--僵尸进程 2-4--wait()和waitpid()销毁僵尸进程 3--信号处理 3-1--signal()函数 3-2--sigaction()函数 3--3--利用信号处理技术消灭僵尸进程 4--基于多任务的并发服务器 5--分割 TCP 的…

webrtc-m79-测试peerconnectionserver的webclient-p2p-demo

1 背景 webrtc的代码中有peerconnectionclient和peerconnectionserver的例子&#xff0c;但是没有对应的web端的例子&#xff0c;这里简单的写了一个测试例子&#xff0c;具体如下&#xff1a; 2 具体操作 2.1 操作流程 2.2 测试效果 使用webclient与peerconnectionclient的…

day34 Set

概述 Set也是集合Collection接口的子接口 Set也是集合Collection接口的子接口 特点&#xff1a;不保证元素有顺序&#xff0c;数组元素不可以重复 HashSet: 底层是基于HashMap的。元素是无序的。元素不可重复&#xff0c;去重机制是依据hashCode()和equals()方法 LinkedHas…

Ubuntu22.04 安装 MongoDB 7.0

稍微查了一些文章发现普遍比较过时。有的是使用旧版本的Ubuntu&#xff0c;或者安装的旧版本的MongoDB。英语可以的朋友可以移步Install MongoDB Community Edition on Ubuntu — MongoDB Manual&#xff0c;按照官方安装文档操作。伸手党或者英语略差的朋友可以按照本文一步步…

使用Mybatis实现基本的增删改查------数据输入

创建一个空的Maven项目,删去src,用作存储pom的父项目 pom中存放下列依赖: <dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version></dependency><de…

【MongoDB】Ubuntu22.04 下安装 MongoDB | 用户权限认证 | skynet.db.mongo 模块使用

文章目录 Ubuntu 22.04 安装 MongoDB后台启动 MongoDBshell 连入 MongoDB 服务 MongoDB 用户权限认证创建 root 用户开启认证重启 MongoDB 服务创建其他用户查看用户信息验证用户权限删除用户 skynet.db.mongo 模块使用authensureIndexfind、findOneinsert、safe_insertdelete、…

在自定义数据集上实现OpenAI CLIP

在2021年1月&#xff0c;OpenAI宣布了两个新模型:DALL-E和CLIP&#xff0c;它们都是以某种方式连接文本和图像的多模态模型。CLIP全称是Contrastive Language–Image Pre-training&#xff0c;一种基于对比文本-图像对的预训练方法。为什么要介绍CLIP呢&#xff1f;因为现在大火…

【C#】关于Array.Copy 和 GC

关于Array.Copy 和 GC //一个简单的 数组copy 什么情况下会触发GC呢[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]public static void Copy(Array sourceArray,long sourceIndex,Array destinationArray,long destinationIndex,long length);当源和目…

浅析Open vSwitch数据结构:哈希表hmap/smap/shash

文章目录 概述hmaphmap数据结构初始化hmap插入节点扩展hmap空间resize函数 删除节点遍历所有节点辅助函数hmap_first辅助函数hmap_next smapsmap数据结构插入节点删除节点查找节点遍历所有节点 shashshash数据结构插入节点删除节点查找节点遍历所有节点 概述 在OVS软件中&…

【网络安全带你练爬虫-100练】第23练:文件内容的删除+写入

目录 0x00 前言&#xff1a; 0x02 解决&#xff1a; 0x00 前言&#xff1a; 本篇博文可能会有一点点的超级呆 0x02 解决&#xff1a; 你是不是也会想&#xff1a; 使用pyrhon将指定文件夹位置里面的1.txt中数据全部删除以后---->然后再将参数req_text的值写入到1.txt …

rsa加密解密java和C#互通

前言 因为第三方项目是java的案例&#xff0c;但是原来的项目使用的是java&#xff0c;故需要将java代码转化为C#代码&#xff0c;其中核心代码就是RSA加密以及加签和验签&#xff0c;其他的都是api接口请求难度不大。 遇到的问题 java和c#密钥格式不一致&#xff0c;java使…

LeetCode(力扣)491. 递增子序列Python

LeetCode491. 递增子序列 题目链接代码 题目链接 https://leetcode.cn/problems/non-decreasing-subsequences/ 代码 class Solution:def backtracking(self, nums, index, result, path):if len(path) > 1:result.append(path[:])uset set()for i in range(index, len…

分类预测 | Matlab实现基于LFDA-SVM局部费歇尔判别数据降维结合支持向量机的多输入分类预测

分类预测 | Matlab实现基于LFDA-SVM局部费歇尔判别数据降维结合支持向量机的多输入分类预测 目录 分类预测 | Matlab实现基于LFDA-SVM局部费歇尔判别数据降维结合支持向量机的多输入分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于局部费歇尔判别数据降维的L…

日常开发小汇总(5)元素跟随鼠标移动(在视口下移动)

<div class"mark"><h1>title</h1><div><p>title 鼠标移动 盒子整体移动</p><p>test</p><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Modi, porro.</p></div></div>cons…

springboot MongoDB 主从 多数据源

上一篇&#xff0c;我写了关于用一个map管理mongodb多个数据源&#xff08;每个数据源&#xff0c;只有单例&#xff09;的内容。 springboot mongodb 配置多数据源 临到部署到阿里云的测试环境&#xff0c;发现还需要考虑一下主从的问题&#xff0c;阿里云买的数据库&#x…