java关于线程同步的问题

问题描述

java关于线程同步的问题

package 线程.TestTeread_5;

/*
push和pop增加减少数组元素,
我的问题是:
为什么去掉push和pop的synchronized修饰关键词时,会报如下错误
异常:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at 线程.TestTeread_5.SynStack.push(TestTeread_5.java:19)
at 线程.TestTeread_5.Producer.run(TestTeread_5.java:57)
at java.lang.Thread.run(Unknown Source)

*/

class SynStack {//同步栈
private char [] data = new char [6];

private int cnt = 0;//cnt表示的是数组有效元素的个数

public synchronized void push(char val){
    while(cnt == data.length)
    {
        try
        {
            this.wait();
            }
        catch(Exception e)
        {}

    }
    this.notify();
    data[cnt] = val;
    System.out.println("生产第"+cnt+"个产品,产品名为"+data[cnt]);
    cnt ++;
}
public synchronized char pop(){

    while(cnt == 0)
    {
        try
        {
            this.wait();//暂停当前线程,转去执行另一个线程
            }
        catch(Exception e)
        {}
    }
    this.notify();
    char Key = data[cnt-1];
    System.out.println("消费第"+cnt+"个产品,产品名为"+Key);
    cnt --;
    return Key;
}

}

class Producer implements Runnable
{
private SynStack ss = null;
public Producer(SynStack ss)
{
this.ss = ss;
}
public void run()
{
char ch;
for(int i=0; i<20; i++)
{

        ch = (char)('a'+i);
        ss.push(ch);
    }

}

}

class Consumer implements Runnable{
private SynStack ss = null;
public Consumer (SynStack ss)
{
this.ss = ss;
}
public void run()
{

    //ss.pop();
    for(int i=0; i<20; i++)
    {
        ss.pop();
    }

}

}
public class TestTeread_5 {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SynStack ss =new SynStack();
    Producer pp = new Producer(ss);
    Consumer cc = new Consumer(ss);

    Thread t1 = new Thread(pp);
    t1.start();
    Thread t2 = new Thread(cc);
    t2.start();
}

}

解决方案

楼主写的这个小例子是经典的线程同步问题,它有个名字,叫“生产者与消费者”。使用多线程的一些企业在笔试面试的时候经常会设计到,对于多线程处理,生产者与消费者只能说是HelloWorld级别的例子。

说说楼主提出的问题。
楼主说为什么去掉synchronized会出问题。楼主是启动了两个线程,两个线程通知操作同一个对象SynStack ss =new SynStack(); 说的准确点,在楼主代码例子中操作的是同一个对象ss的同一个属性char [] data 这个数组。这样就会出现多线程同步的问题。试想一下,还没开始生产,数组里面没数据,你就从数组里面拿数组就会出问题。

在楼主的例子里面,还好只有一个生产者线程,一个消费者线程,所以notify的时候基本上不会出问题,当前线程在运行,notify时,当然是notify另一个线程。如果有两个生产者和两个消费者,这时候就会出问题的,notify是随机唤醒正在wait的线程,你都不知道到底哪个线程会被唤醒。

最后看到在其他网友回答中,楼主追问了一个wait中的线程被notify了之后,是从方法头开始执行还是接着wait之后执行。答案是接着wait之后执行。所以为什么建议对wait语句使用while包起来,表示唤醒之后再次去检查下wait的条件,满足的话继续wait,为什么说建议这么做呢?因为能使wait的线程醒过来的方式不止是去notify,一些异常情况也能使线程醒过来。

解决方案二:

就是数据冲突了,一个出,一个进,可能已经没有元素了,但是你另一个线程中还在访问,导致出错,或者两个线程读写发生冲突出错

解决方案三:

 wait,notify执行必须拥有对象的锁,这里是this,如果方法不加同步synchronized,只要连续执行this.wait或者this.notify中任何2次,都会报错,因为没有对象锁。

解决方案四:

因为notify()必须是在同步方法或者同步块中被使用啊,亲

解决方案五:

http://blog.csdn.net/zhouxiaoyun0228/article/details/7757313

时间: 2025-01-20 19:50:05

java关于线程同步的问题的相关文章

java中线程同步,线程让步,线程休眠的区别和联系是什么

问题描述 java中线程同步,线程让步,线程休眠的区别和联系是什么 java中线程同步,线程让步,线程休眠的区别和联系是什么 线程的本质还是一个运行中的类, 解决方案 线程同步:是保证多线程安全访问竞争资源的一种手段,java中常用的是加锁机制即synchronized同步代码块实现的. 线程让步的方法是yield(),休眠方法是sleep().sleep()方法和yield()方法都是Thread类的静态方法,都会使当前处于运行状态的线程放弃CPU,把运行机会让给别的线程. 两者的区别在于:s

深入解析Java的线程同步以及线程间通信_java

Java线程同步 当两个或两个以上的线程需要共享资源,它们需要某种方法来确定资源在某一刻仅被一个线程占用.达到此目的的过程叫做同步(synchronization).像你所看到的,Java为此提供了独特的,语言水平上的支持. 同步的关键是管程(也叫信号量semaphore)的概念.管程是一个互斥独占锁定的对象,或称互斥体(mutex).在给定的时间,仅有一个线程可以获得管程.当一个线程需要锁定,它必须进入管程.所有其他的试图进入已经锁定的管程的线程必须挂起直到第一个线程退出管程.这些其他的线程被

详解Java传统线程同步通信技术

编写代码实现以下功能 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着再回到主线程又循环100次,如此循环50次. 分析 1)子线程循环10次与主线程循环100次必须是互斥的执行,不能出现交叉,下面代码中通过synchronized关键字实现此要求: 2)子线程与主线程必须交替出现,可以通过线程同步通信技术实现,下面代码中通过bShouldSub变量实现此要求: 其他需要注意的地方 1)其中business变量必须声明为final类型,因为在匿名内部类和局部内部类中调用

java 实现线程同步的方式有哪些_java

什么是线程同步? 当使用多个线程来访问同一个数据时,非常容易出现线程安全问题(比如多个线程都在操作同一数据导致数据不一致),所以我们用同步机制来解决这些问题. 实现同步机制有两个方法: 1.同步代码块: synchronized(同一个数据){} 同一个数据:就是N条线程同时访问一个数据. 2. 同步方法: public synchronized 数据返回类型 方法名(){} 就是使用 synchronized 来修饰某个方法,则该方法称为同步方法.对于同步方法而言,无需显示指定同步监视器,同步

java非常规线程同步问题一个!

问题描述 我现在有一个这样的资源类,可能的方法如下所示class A {List test:set(); // 初始化test,并赋值reset(); // 请空test,并对test重新赋值get(int index); // 取test中的某个值}一般情况下test初始化后有多个线程会调用get()方法取值,为了保证效率也不需要同步get()方法,但一定概率下会有其他线程对test调用reset()方法,我的需求是:当有线程调用reset()方法时(同一时刻只有一个线程调用reset()),

java web-多线程同步银行多账户取钱

问题描述 多线程同步银行多账户取钱 最近一直在想一个多线程的问题,举个例子 比如javaweb银行项目,同时两个人在异地个存取200元如何保证不出差错. 两个人在异地同时登陆的话其实在系统中是属于两个数据相同的对象(spring+hibernate)如果使用对象的排它锁也不会起作用.这种需求应该怎样实现那? 解决方案 跪求大神答疑解惑~~~~(>_<)~~~~

java线程同步 死锁问题

问题描述 java线程同步 死锁问题 写了一个java中线程同步的死锁问题,但是输出结果就是不对,劳烦前辈指点指点.源代码如下: public class TestDeadLock implements Runnable{ public static int flag = 1; static Object o1 = new Object(); static Object o2 = new Object(); public void run(){ System.out.println(""

JAVA线程同步实例教程_java

线程是Java程序设计里非常重要的概念,本文就以实例形式对此加以详细解读.具体分析如下: 首先,线程加锁有什么用处呢?举个例子:比如你现在有30000块大洋在银行存着,现在你到银行取钱,当你输入密码完成后,已经输入取款金额,比如你输入的是20000,就是在银行给你拿钱这个时刻,你老婆也去银行取这笔钱,你老婆同样取20000,因为此时你的账上仍然是30000,所以银行同样的操作在你老婆那端又进行了一遍,这样当你们两个完成各自操作后,银行记录的你账上还应该有10000块存款,这样是不是很爽.解决这个

java-Java关于线程同步的问题

问题描述 Java关于线程同步的问题 package com.thread.tongbu; public class Buffer { private int value; private boolean isEmpty=true; public synchronized void put(int i) { while(!this.isEmpty) try { this.wait(); } catch (InterruptedException e) {} this.value=i; this.