java多线程之-----对象及变量的并发访问1(synchronized同步方法)
来源:互联网 发布:js获取字符串字节长度 编辑:程序博客网 时间:2024/05/16 12:35
方法内部的变量为线程安全的
“非线程安全”问题存在于“实例变量中”如果是方法内部的私有变量,则不存在“非线程安全”的问题,所得的结果也就是“线程安全”的了
实例变量非线程安全
如果多个线程共同访问一个对象中的实例变量,则有可能出现“非线程安全”的问题。用线程访问的对象中如果有多个实例变量,则运行的结果可能有可能出现交叉的情况。如果只有一个实例变量则有可能出现覆盖的情况,看下面的测试:创建新的项目,HasSelfPrivateNum.java的代码如下:
public class HasSelfPrivateNum { private int num = 0; 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(); } }}
ThreadA如下:
public class ThreadA extends Thread{ private HasSelfPrivateNum selfPrivateNum; public ThreadA(HasSelfPrivateNum selfPrivateNum) { // TODO Auto-generated constructor stub super(); this.selfPrivateNum = selfPrivateNum; } @Override public void run() { // TODO Auto-generated method stub super.run(); selfPrivateNum.addI("a"); }}
ThreadB:
public class ThreadB extends Thread{ private HasSelfPrivateNum selfPrivateNum; public ThreadB(HasSelfPrivateNum selfPrivateNum) { // TODO Auto-generated constructor stub super(); this.selfPrivateNum = selfPrivateNum; } @Override public void run() { // TODO Auto-generated method stub super.run(); selfPrivateNum.addI("b"); }}
测试代码:
public class Test1 { public static void main(String[] args) throws InterruptedException { HasSelfPrivateNum hasSelfPrivateNum = new HasSelfPrivateNum(); ThreadA a = new ThreadA(hasSelfPrivateNum); a.start(); ThreadB b = new ThreadB(hasSelfPrivateNum); b.start(); }}
运行结果:
由上面个的结果可得到:
如果两个线程同时操作业务对象的实例变量,则有可能会出现非线程安全的问题,我们只需要在前面加上synchrionized字即可。更改后的代码如下:
public class HasSelfPrivateNum { private int num = 0; synchronized 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(); } }}
再次运行代码:
实验结论:在两个线程访问同一个对象的同步方法时一定是线程安全的。
多个对象多个锁
上面的HasSelfPrivateNum类中有同步方法addI,说明此方法应该被顺序调用。修改执行代码如下:
public class Test1 { public static void main(String[] args) throws InterruptedException { HasSelfPrivateNum hasSelfPrivateNum = new HasSelfPrivateNum(); HasSelfPrivateNum hasSelfPrivateNum2 = new HasSelfPrivateNum(); ThreadA a = new ThreadA(hasSelfPrivateNum); a.start(); ThreadB b = new ThreadB(hasSelfPrivateNum2); b.start(); }}
运行结果;
上面的事例是两个线程分别访问同一个类的两个不同实例的相对名称的同步方法,效果确实以异步的方式运行的,本示例由于创建了两个业务对象,在系统中产生了两个锁。所以运行结果是异步的,打印的结果就是先打印b,再打印a。明明加了synchronized关键字,但打印的顺序却是不是同步的,是交叉的,为什么是这样的结果?关键字synchronized取得的锁都是对象锁,而不是一段代码或方法(函数)当做锁,所以上面实例,那个线程先执行带synchronized关键字的方法,那个线程就持有该方法所属有的锁Lock。其他线程只能呈现等待状态。前提是多个线程访问同一个对象。如果多个线程访问多个队形,JVM就会创建多个锁,上面的实例就是创建了两个HasSelfPrivateNum 类的对象,所以就会产生两个锁
阅读全文
1 0
- java多线程之-----对象及变量的并发访问1(synchronized同步方法)
- 第二章、对象及变量的并发访问 之 synchronized 同步方法(1)
- 第二章、对象及变量的并发访问 之 synchronized 同步方法(2)
- JAVA多线程-对象及变量的并发访问(一)synchronized详解
- Java多线程之对象及变量的并发访问
- 多线程编程核心技术读书笔记(二):对象及变量的并发访问(synchronized关键字)
- java多线程编程2--对象及变量的并发访问
- java多线程编程3--对象及变量的并发访问
- Java多线程--对象及变量的并发访问
- java 多线程(4) 线程同步之锁(synchronized) / 死锁 / 两个锁定对象期间访问(修改)其变量的面试
- 对象及变量的并发访问——Synchronized详解
- JAVA多线程-对象及变量的并发访问(二)volatile关键字
- 《Java多线程编程核心技术》(二)对象及变量的并发访问
- Java多线程编程核心技术---对象及变量的并发访问(一)
- Java多线程编程核心技术---对象及变量的并发访问(二)
- Java多线程二——对象及变量的并发访问(概念理解)
- 【java多线程编程核心技术】2.对象及变量的并发访问(上)-笔记总结
- 【java多线程编程核心技术】2.对象及变量的并发访问(下)-笔记总结
- Android Studio中Git的使用说明书
- css position
- office 2013下载及激活
- Java学习之路:不走弯路,就是捷径
- 如何使用UCI数据集
- java多线程之-----对象及变量的并发访问1(synchronized同步方法)
- Win10解决无法访问其他机器共享的问题
- [bzoj-2140]稳定婚姻 题解
- 中小企业如何才能招聘到合适的程序员?
- struts,spring和Hibernate整合(注解式)
- 指针与词典
- 使用注解写SSH整合
- 极限
- Minimum Number of Arrows to Burst Balloons_Week8