线程的同步与死锁 (同步 synchronization,死锁 deadlock)
        多线程的操作方法
    
        1.线程同步的产生与解决
        2.死锁的问题

    同步问题的的引出
        如果要想进行同步的操作,那么很明显就是多个线程需要访问同一资源
        
        范例:以卖票程序为例

package cn.mysterious.study3;

class MyThread implements Runnable{
private int ticket = 5;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
if (this.ticket > 0) {
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
public class StudyThread { public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}

于是下面开始挖掘本程序所存在的问题
            
        范例:观察程序的问题

package cn.mysterious.study3;

class MyThread implements Runnable{
private int ticket = 5;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
if (this.ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
public class StudyThread { public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}
// 结果出现了负数

bane这样的操作就属于线程的不同步的操作,所以发现多个线程操作时必须要考虑到资源同步的问题

    实现同步操作
        整个代码之中发现有一个逻辑上的流程错误了,以上的程序中,将判断是否有票,延迟,卖票分为了三个部分
        那么实际上每个线程如果要执行卖票的话,其他线程应该等待当前线程执行完毕后才可以进入
        
        如果要想在若干个代码上实现锁这个概念,那么就需要通过使用同步代码块或者同步方法来解决
        
        1.同步代码块
            使用 synchronized 关键字定义的代码块就称为同步代码块,但是在进行同步的时候需要设置有一个同步对象,那么往往可以使用 this 同步当前对象

package cn.mysterious.study3;

class MyThread implements Runnable{
private int ticket = 500;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
synchronized (this) {
if (this.ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
}
}
public class StudyThread { public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}

加入同步之后整个代码执行的速度已经变慢了,而已不像美誉同步的时候那样多个线程一起进入到方法之中
            异步的执行速度要快于同步的执行速度,但是异步的操作属于非线程安全的操作,而同步的操作属于线程的安全操作
            
        2.同步方法    
            但是对于同步操作,除了用于代码块定义之外,也可以在方法上定义同步操作

package cn.mysterious.study3;

class MyThread implements Runnable{
private int ticket = 500;
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 1000; i++) {
sale();
}
}
public synchronized void sale(){ // 卖票
if (this.ticket > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ",ticket = "+this.ticket --);
}
}
}
public class StudyThread { public static void main(String[] args) throws Exception {
MyThread mt = new MyThread();
Thread t1 = new Thread(mt,"票贩子A");
Thread t2 = new Thread(mt,"票贩子B");
Thread t3 = new Thread(mt,"票贩子C");
t1.start();
t2.start();
t3.start();
}
}

在多个线程访问同一资源时一定要考虑到数据的同步问题,同步就使用 synchronized 关键字
    死锁分析(了解)
        很明显,死锁是一种不确定的状态,对于死锁的操作应该出现的越少越好,下面的代码只是一个死锁的演示,代码不做任何实际的意义

package cn.mysterious.study3;

class Kidnapper{  // 绑匪
public synchronized void say(Landlord dz){
System.out.println(" 绑匪说:给我3亿美金,放了你儿子!");
dz.get();
}
public synchronized void get(){
System.out.println("绑匪得到钱");
}
}
class Landlord{ // 地主
public synchronized void say(Kidnapper bf){
System.out.println(" 地主说:放了我儿子,再给钱!");
bf.get();
}
public synchronized void get(){
System.out.println("救回.....");
}
}
public class StudyThread implements Runnable{
private Kidnapper bf = new Kidnapper();
private Landlord dz = new Landlord();
public StudyThread (){
new Thread(this).start();
dz.say(bf);
}
public static void main(String[] args) throws Exception {
new StudyThread();
}
@Override
public void run() {
// TODO Auto-generated method stub
bf.say(dz);
}
}

面试题:请问多个线程访问同一资源时可能带来什么问题?以及会产生什么样的附加问题?
             多个线程访同一资源时必须考虑同步问题,可以使用 synchronized 定义同步代码块或者是同步方法
             程序中如果出现过多的同步那么就将产生死锁
            
    总结
        如果看见 synchronized 声明的方法,一定有爱记住这是一个同步方法,属于线程安全的操作

菜鸡的Java笔记 - java 线程的同步与死锁 (同步 synchronization,死锁 deadlock)的更多相关文章

  1. Java 笔记 —— java 和 javac

    Java 笔记 -- java 和 javac h2{ color: #4ABCDE; } a{ text-decoration: none !important; } a:hover{ color: ...

  2. java笔记--使用线程池优化多线程编程

    使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库 ...

  3. java 笔记(5) —— 线程,yield,join

    一.线程各个状态与转换: 新建状态:用new语句创建的线程对象处于新建状态,此时它和其它的java对象一样,仅仅在堆中被分配了内存 .就绪状态:当一个线程创建了以后,其他的线程调用了它的start() ...

  4. java笔记--守护线程的应用

    守护线程的应用 Java中的线程可以分为两类,即用户线程和守护线程.用户线程是为了完成任务,而守护线程是为其他线程服务 --如果朋友您想转载本文章请注明转载地址"http://www.cnb ...

  5. java笔记--关于线程死锁

    关于线程死锁 什么是死锁: 在编写多线程的时候,必须要注意资源的使用问题,如果两个或多个线程分别拥有不同的资源, 而同时又需要对方释放资源才能继续运行时,就会发生死锁. 简单来说:死锁就是当一个或多个 ...

  6. 菜鸡的Java笔记 - java 线程常用操作方法

    线程常用操作方法        线程的命名操作,线程的休眠,线程的优先级            线程的所有操作方法几乎都在 Thread 类中定义好了            线程的命名和取得      ...

  7. 菜鸡的Java笔记 java基础类库 BaseClassLibrary

    java基础类库 BaseClassLibrary        StringBuffer 类的特点        StringBuffer,StringBuilder,String 类之间的关系   ...

  8. 菜鸡的Java笔记 - java 断言

    断言:assert (了解)        所谓的断言指的是在程序编写的过程之中,确定代码执行到某行之后数据一定是某个期待的内容        范例:观察断言 public class Abnorma ...

  9. 菜鸡的Java笔记 - java 正则表达式

    正则表达式 RegularExpression        了解正则表达式的好处        正则表达式的基础语法        正则表达式的具体操作            content (内容 ...

随机推荐

  1. [Linux]Ansible自动化运维② - 工具与模块

    目录 一.Ansible的工具 1.1 Ansible的工作前提 1.2 Ansible的安装文件 1.3 Ansible的配置文件 1.4 Ansible的相关工具 1.4.1 [帮助工具]Ansi ...

  2. CQOI2021 退役记

    Day -1 晚上去了酒店然后就睡觉了. Day 1 进考场之前互相奶. 进了考场之后看题,发现T1很水(伏笔1,然后直接开始写 \(\Theta(n\log^2n)\)(二分+动态开点线段树),调了 ...

  3. FastAPI 学习之路(三十二)创建数据库

    在大型的web开发中,我们肯定会用到数据库操作,那么FastAPI也支持数据库的开发,你可以用 PostgreSQL MySQL SQLite Oracle 等 本文用SQLite为例.我们看下在fa ...

  4. [no_code][Beta]设计和计划

    2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 Beta设计和计划 我们在这个课程的目标是 远程协同工作,采用最新技术开发软件 这个作业在哪个具体 ...

  5. [对对子队]会议记录5.25(Scrum Meeting11)

    今天已完成的工作 吴桐雨 ​ 工作内容:设计第10.11关 ​ 相关issue:设计额外关卡 ​ 相关签入:level10 level11 吴昭邦 ​ 工作内容:写测试代码 ​ 相关issue:测试初 ...

  6. [对对子队]会议记录4.11(Scrum Meeting 2)

    今天已完成的工作 何瑞 ​ 工作内容:完成指令的衔接:完成合成指南界面的制作:初步实现成本系统 ​ 相关issue:实现用户指令编辑系统的逻辑 马嘉 ​ 工作内容:完成游戏内暂停界面 ​ 相关issu ...

  7. MySQL 8.0安装 + 配置环境变量 + 连接 cmd

    MySQL 安装教程 搜索 MySQL,进入官网,找到 download 点击适用于 window community 版本,点击图中第二个 450.7 M 的安装包进行下载 这里有五个选项,选择第二 ...

  8. 微信小程序 scroll-view 完成上拉加载更多

    我们经常在软件客户端上看到这么一个功能,当我们阅读信息浏览到文章的末尾时,通常会加载出更多的信息.比如,我们在简书客户端上浏览推荐文章时,浏览到屏幕的末尾,此时又加载出了另一页的推荐文章,即实现了上拉 ...

  9. SpringCloud+RocketMQ实现分布式事务

    随着互联网公司的微服务越来越多,分布式事务已经成为了我们的经常使用的.所以我们来一步一步的实现基于RocketMQ的分布式事务.接下来,我们将要做的主题写出来. RocketMQ的分布式事务结构和说明 ...

  10. 链表中倒数第K个结点 牛客网 剑指Offer

    链表中倒数第K个结点 牛客网 剑指Offer 题目描述 输入一个链表,输出该链表中倒数第k个结点. # class ListNode: # def __init__(self, x): # self. ...