线程问题——同步和死锁

【问题引出】:比如说对于买票系统,有下面的代码:

 1 class hello implements Runnable {
 2     private static int count=5;
 3     public void run() {
 4         for(int i=0;i<10;++i){
 5             if(count>0){
 6                 try{
 7                     Thread.sleep(1000);
 8                 }catch(InterruptedException e){
 9                     e.printStackTrace();
10                 }
11                 System.out.println(count--);
12             }
13         }
14     }
15
16     public static void main(String[] args) {
17         hello he=new hello();
18         Thread h1=new Thread(he);
19         Thread h2=new Thread(he);
20         Thread h3=new Thread(he);
21         h1.start();
22         h2.start();
23         h3.start();
24     }
25 }

【运行结果】

5
4
3
2
1
0
-1

这里出现了-1,显然这个是错的。,应该票数不能为负值。

如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,

其他的线程必须等到这个线程结束之后才能继续执行。

【使用线程同步解决问题】

采用同步的话,可以使用同步代码块和同步方法两种来完成。

(一)同步代码块

语法格式:

synchronized(同步对象){

 //需要同步的代码

}

但是一般都把当前对象this作为同步对象。

比如对于上面的买票的问题,如下(修改run方法):

public void run() {
        for(int i=0;i<10;++i){
            synchronized(this){
                if(count>0){
                    try{
                        Thread.sleep(1000);
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println(count--);
                }
            }
        }
    }

【运行结果】:(每一秒输出一个结果)

5

4

3

2

1

(二)同步方法

语法格式为

synchronized 方法返回类型方法名(参数列表){

    // 其他代码

}

修改run方法

public void run() {
        for (int i = 0; i < 10; ++i) {
            sale();
        }
    }

    public synchronized void sale() {
        if (count > 0) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(count--);
        }
    }

运行结果同上。

提醒一下,当多个线程共享一个资源的时候需要进行同步,但是过多的同步可能导致死锁。

时间: 2024-10-29 10:45:54

线程问题——同步和死锁的相关文章

线程的同步与死锁

在多线程中,同步与死锁概念很重要,在本章中必须了解以下几点: 1)哪里需要同步. 2)如何实现同步,了解代码即可. 3)及实现同步后有哪些副作用. 代码并不要求可以完整编写,但是概念必须清楚. 具体内容 1.1问题引出 以买火车票为例,不管多少地方可以买火车票,最终一趟列车的车票数量是固定的,如果把各个售票点理解为线程的话,则所有线程应该共同拥有同一份票数. package Thread1; class MyThread implements Runnable{ private int tick

Java总结(十)—实现Runnable接口创建线程,线程安全同步,死锁(哲学家进餐问题),读写锁

一.通过实现Runnable接口创建线程 定义实现Runnable接口的类 (1)Runnable接口中只有一个方法public void run();用来定义线程运行体: class MyRun implements Runnable(){ public void run(){ 线程执行的具体代码 } } (2)创建线程的实例的时候将这个类的实例作为参数传递到线程实例内部.然后再启动: Thread thread=new Thread(new MyRun()); Thread.start();

线程4 同步和死锁

线程可以在一定程度上提高程序运行的效率(并发执行,节省时间.),但也会产生一些副作用(数据脏读,死锁). 数据脏读可以通过同步技术控制,死锁通过约定解决. class Increment//同步解决脏读    {        private int n = 0;        private int max;        public Increment(int max)        {            this.max = max;        }        public i

线程的同步和死锁

要是一个线程池如果通过Runnable接口实现,则意味着类中的属性将被多个线程程序共享,产生的问题就是资源同步的问题: 1.线程的延时会导致其他线程会提前或延后对资源共享块进行操作. 2.要是多个线程在处理一个问题时都处在判断对方的执行状态时,线程会变成死锁. 上面的问题我们可以通过同步进行解决(注:多个线程共享同一资源时需要进行同步,一保证资源操作的完整性,但是过多的同步就会造成死锁. package Rubbableclass; /* * 线程中的延时函数所产生的问题 * */ class

多线程——线程同步,死锁

线程同步: 为什么需要同步 ①   线程同步是为了防止多个线程访问一个数据对象时,对数据造成破坏. ②   线程的同步是保证多线程安全访问竞争资源的一种手段. 同步和锁 ①   Java中每一个对象都有一个内置锁. ②   当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁:当程序运行到synchronized同步代码块时,自动获得锁定对象的锁. ③   获得一个对象的锁也称为获取锁.锁定对象.在对象上锁定或在对象上同步.当程序运

线程的同步与互斥,死锁

线程的同步与互斥 多个线程同时访问共享数据时可能会发生冲突,比如两个线程同时把一个全局变量加1,结果可能不是我们所期待的: 我们看这段代码的执行结果: #include <stdio.h> #include <stdlib.h> #include <pthread.h> static int g_count=0; void *thread(void *arg) { int index=0; int tmp=0; while(index++<5000) { tmp=

Java之线程,常用方法,线程同步,死锁

1, 线程的概念 进程与线程 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小.(线程是cpu调度的最小单位) 切换而不是同步 一个程序中的方法有几条执行路径, 就有几个线程 Java中线程的生命周期 Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t =

Java多线程编程(三)线程的优先级、同步与死锁

线程的优先级: 线程的优先级分为三种,分别是: 1-MIN_PRIORITY 10-MAX_PRIORITY 5-NORM_PRIORITY 如果什么都不设置默认值是5 线程的优先级可以影响线程的执行顺序,当然这里指的是有可能影响,不会一定影响.在默认状态下(比如说主线程)它的默认值是5 具体代码演示: package com.yeqc.thread; class ThRun implements Runnable{ @Override public void run() { for(int i

C#:多线程、线程同步与死锁

推荐阅读: C#线程系列讲座(1):BeginInvoke和EndInvoke方法 C#线程系列讲座(2):Thread类的应用 C#线程系列讲座(3):线程池和文件下载服务器 C#线程系列讲座(4):同步与死锁 C#线程系列讲座(5):同步技术之Monitor C#中多线程同步的Monitor理解