【Java多线程编程核心技术】2.对象及变量的并发访问(上)-笔记总结

相关链接:
【java多线程编程核心技术】1.Java多线程技能-笔记总结
【Java多线程编程核心技术】2.对象及变量的并发访问(上)-笔记总结
【Java多线程编程核心技术】2.对象及变量的并发访问(下)-笔记总结
【Java多线程编程核心技术】3.线程间通信 -笔记总结
【Java多线程编程核心技术】4.Lock的使用-笔记总结
【Java多线程编程核心技术】5.定时器Timer-笔记总结
【Java多线程编程核心技术】6.单例模式与多线程-笔记总结
【Java多线程编程核心技术】7.拾遗增补-笔记总结

synchronized同步方法

方法内的变量为线程安全

非线程安全”问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在“非线程安全”问题

实例变量非线程安全

package service;
public class HasSelfPrivateNum {
   
     private int num = 0;
//   synchronized public void addI(String username) {
   
     public void addI(String username) {  //此处未同步,会发生"非线程安全"问题
          try {
              if (username.equals("a")) {
                   num = 100;
                   System.out.println("a set over!");
                   Thread.sleep(2000);
              } else {
                   num = 200;
                   System.out.println("b set over!");
              }
              System.out.println(username + " num=" + num);
          } catch (InterruptedException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
     }
}
package extthread;
import service.HasSelfPrivateNum;
public class ThreadA extends Thread {
   
     private HasSelfPrivateNum numRef;
     public ThreadA(HasSelfPrivateNum numRef) {
          super();
          this.numRef = numRef;
     }
     @Override
     public void run() {
          super.run();
          numRef.addI("a");
     }
}
package extthread;
import service.HasSelfPrivateNum;
public class ThreadB extends Thread {
   
     private HasSelfPrivateNum numRef;
     public ThreadB(HasSelfPrivateNum numRef) {
          super();
          this.numRef = numRef;
     }
     @Override
     public void run() {
          super.run();
          numRef.addI("b");
     }
}
package test;
import service.HasSelfPrivateNum;
import extthread.ThreadA;
import extthread.ThreadB;
public class Run {
   
    public static void main(String[] args) {
        HasSelfPrivateNum numRef = new HasSelfPrivateNum();
        ThreadA athread = new ThreadA(numRef);
        athread.start();
        ThreadB bthread = new ThreadB(numRef);
        bthread.start();
    }
}

非同步输出结果:
a set over!
b set over!
b num=200
a num=200
加入synchronized关键字同步后,输出结果:
a set over!
a num=100
b set over!
b num=200

用线程访问的对象中如果有多个实例变量,则运行的结果有可能出现交叉的情况
如果对象仅有一个实例变量,则有可能出现覆盖的情况(如上面例子)
需在public void addI(String username)前加关键字synchronized实现同步
在两个线程访问同一个对象中的同步方法时一定是线程安全的(原文

多个对象多个锁

其他代码与上例相同(+synchronized关键字后的)
package test;
import service.HasSelfPrivateNum;
import extthread.ThreadA;
import extthread.ThreadB;
public class Run {
   
    public static void main(String[] args) {
        HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
        HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();
        ThreadA athread = new ThreadA(numRef1);
        athread.start();
        ThreadB bthread = new ThreadB(numRef2);
        bthread.start();
    }
}
输出结果:
a set over!
b set over!
b num=200
a num=100

两个线程分别访问同一个类的两个不同实例的相同名称的同步方法,效果却是以异步的方式运行的。
原因:此处关键字synchronized取得的锁是对象锁。在多个线程访问同一个对象时,哪个线程先执行带synchronized关键字的方

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值