多个线程N个对象锁

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by csj on 2017/3/27.
 * 虽然在赋值的时候进行了同步,但在取值的时候有可能出现一些意想不到的意外,比如在读取实例变量时,该值已经被其他线程更改过了,这种情况就是脏读,根本原因是多个线程争夺实例变量引起的
 *
 *
 * 总结:针对同一个对象锁
 * 其中一个线程调用了PublicVar 对象的setValue()时,该线程就获得了这个对象的锁,其他也是使用这个对象锁的线程需要等待该线程执行完毕,但是可以调用其他的非同步的方法
 * 当该线程调用了PublicVar 对象的setValue()时,其他线程如果要调用synchronized关键字的非setValue(),必须等该线程已经执行了一个完整的任务,
 * 针对两个对象锁或者多个对象锁如下
 * 两个线程之间获得对象锁不一样不需要等待,就不需要等待另一个线程的执行完成才能执行。
 */
public class PublicVar {


    Logger logger = LoggerFactory.getLogger(PublicVar.class);
    public String username = "a";
    public String password = "aa";

    //同步方法setValue() 的锁属于类PublicVar的实例
    synchronized public void setValue(String username, String password) {
        try {
            this.username = username;

            Thread.sleep(5000);

            this.password = password;

            logger.info("setValue  thread name = {}, username={}, password ={} ", Thread.currentThread().getName(), username, password);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    /*
    * 第一种情况:
    * 如果这个方法没有添加synchronized,那么可以在任意时候进行调用,
    * main函数输出的结果如下
    * 2017-03-27 21:36:57.276 [main] INFO  PublicVar - thread name =main , username =b , password=aa
    * 2017-03-27 21:37:02.071 [Thread-0] INFO  PublicVar - setValue  thread name = Thread-0, username=b, password =bb
    *
    * 第二种情况
    * 在这个函数中添加了synchronized,那么在main(),必须先执行完一个线程后,另一个线程才能访问,因为两个线程用的是同一个对象锁
    * 2017-03-27 21:46:15.744 [Thread-0] INFO  PublicVar - setValue  thread name = Thread-0, username=b, password =bb
    * 2017-03-27 21:46:15.748 [main] INFO  PublicVar - thread name =main , username =b , password=bb
    *
    * */
    synchronized public void getValue(){

        logger.info("thread name ={} , username ={} , password={}", Thread.currentThread().getName(), username, password);
    }

}
 
 
/**
 * Created by csj on 2017/3/25.
 */
public class ThreadA extends Thread {

    private PublicVar publicVar;

    public ThreadA(PublicVar publicVar) {
        super();
        this.publicVar = publicVar;
    }

    @Override
    public void run() {
        super.run();
        publicVar.setValue("b","bb");
    }
}

 
/**
 * Created by csj on 2017/3/25.
 * 两个线程分别访问同一个类的两个不同实例的相同名称的同步方法,效果是以异步的方式运行的,没有同步,各自有锁
 * 原因:synchronized 取的是对象锁,而不是把一段代码或方法当作锁,,所以哪个线程运行对应的方法,就持有该方法所属对象的锁Lock
 * 那么多个线程访问的同一个对象的情况下,其他线程如果要使用这个对象锁就只能先等待。
 * 如果多个线程访问多个对象,则jvm会创建多个锁。
 */
public class Run {

    public static void main(String[] args) {
        try {
            PublicVar publicVar = new PublicVar();
            PublicVar publicVar1 = new PublicVar();
            ThreadA threadA = new ThreadA(publicVar);
            ThreadA threadB = new ThreadA(publicVar1);
        threadB.start();
            threadA.start();
            Thread.sleep(200);
            publicVar.getValue();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值