java线程安全

共享数据

同步锁

sychronized

Lock lock=new ReetrantLock();

lock.lock() lock.unlock();

造成死锁的原理

线程等待与唤醒(线程通信)

在开始讲解等待唤醒机制之前,有必要搞清一个概念——线程之间的通信:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制。
等待唤醒机制所涉及到的方法:
 wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。
 notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。
 notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。
其实,所谓唤醒的意思就是让 线程池中的线程具备执行资格。必须注意的是,这些方法都是在 同步中才有效。同时这些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。
仔细查看JavaAPI之后,发现这些方法 并不定义在 Thread中,也没定义在Runnable接口中,却被定义在了Object类中,为什么这些操作线程的方法定义在Object类中?
因为这些方法在使用时,必须要标明所属的锁,而锁又可以是任意对象。能被任意对象调用的方法一定定义在Object类中。

等待与唤醒要锁对象调用

package cn.itcast.demo4;
/*
 *  输入的线程,对资源对象Resource中成员变量赋值
 *  一次赋值 张三,男
 *  下一次赋值 lisi,nv
 */
public class Input implements Runnable {
    private Resource r ;

    public Input(Resource r){
        this.r = r;
    }

    public void run() {
        int i = 0 ;
        while(true){
          synchronized(r){
              //标记是true,等待
                if(r.flag){
                    try{r.wait();}catch(Exception ex){}
                }

                if(i%2==0){
                    r.name = "张三";
                    r.sex = "男";
                }else{
                    r.name = "lisi";
                    r.sex = "nv";
                }
                //将对方线程唤醒,标记改为true
                r.flag = true;
                r.notify();
          }
            i++;
        }
    }

}
package cn.itcast.demo4;
/*
 *  输出线程,对资源对象Resource中成员变量,输出值
 */
public class Output implements Runnable {
    private Resource r ;

    public Output(Resource r){
        this.r = r;
    }
    public void run() {
        while(true){
          synchronized(r){  
              //判断标记,是false,等待
            if(!r.flag){
                try{r.wait();}catch(Exception ex){}
            }
            System.out.println(r.name+".."+r.sex);
            //标记改成false,唤醒对方线程
            r.flag = false;
            r.notify();
          }
        }
    }

}
package cn.itcast.demo4;
/*
 *  定义资源类,有2个成员变量
 *  name,sex
 *  同时有2个线程,对资源中的变量操作
 *  1个对name,age赋值
 *  2个对name,age做变量的输出打印
 */
public class Resource {
    public String name;
    public String sex;
    public boolean flag = false;
}
package cn.itcast.demo4;
/*
 *  开启输入线程和输出线程,实现赋值和打印值
 */
public class ThreadDemo{
    public static void main(String[] args) {

        Resource r = new Resource();

        Input in = new Input(r);
        Output out = new Output(r);

        Thread tin = new Thread(in);
        Thread tout = new Thread(out);

        tin.start();
        tout.start();
    }
}
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_23052951/article/details/80690385
个人分类: java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭