synchronized同步方法《一》
1.方法内的变量为线程安全
"非线程安全"问题存在于"实例变量"中,如果是方法内部的私有变量,则不存在"非线程安全"问题,所得结果也就是"线程安全"了。下面我们来编写一个"线程安全"的例子:
1.1 HasSelfPrivate类如下:
package edu.ymm.about_thread; public class HasSelfPrivate {
public void add1(String username) {
try {
int num = 0; //这就是方法类的变量
if(username.equals("a")) {
num = 100;
System.out.println("a set over");
Thread.sleep(2000); //用来等待b }else {
num = 200;
System.out.println("b set over");
}
System.out.println(username + "num = " + num);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1.2 创建一个ThreadA类:
package edu.ymm.about_thread; public class ThreadA extends Thread { private HasSelfPrivate numself;
public ThreadA(HasSelfPrivate numself) {
super();
this.numself = numself;
} @Override
public void run() {
super.run();
numself.add1("a ");
} }
1.3 创建一个ThreadB类:
package edu.ymm.about_thread; public class ThreadB extends Thread { private HasSelfPrivate numself;
public ThreadB(HasSelfPrivate numself) {
super();
this.numself = numself;
}
@Override
public void run() {
super.run();
numself.add1("b ");
}
}
1.4 来测试一下这个例子:
package edu.ymm.about_thread; public class Test { public static void main(String[] args) { HasSelfPrivate hPrivate = new HasSelfPrivate();
ThreadA threadA = new ThreadA(hPrivate);
threadA.start();
ThreadB threadB =new ThreadB(hPrivate);
threadB.start();
} }
执行结果如下:
可见,方法中的变量不存在非线程安全问题,永远是线程安全的。原因就是方法内部的变量是私有的。
2.实例变量非线程安全
(1):"非线程安全"其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是“脏读”,也就是取到的数据其实是被更改过的。而“线程安全”就是以获得的实例变量的值是经过同步处理的,不会出现脏读的现象。
(2):用线程访问的对象中如果有多个实例变量,则运行的结果有可能出现交叉情况。
(3):如果对象仅有1个实例变量,则可能出现覆盖的情况。
下面举一个例子:
2.1 HasSelfPrivate类如下:
package edu.ymm.about_thread1; public class HasSelfPrivate {
private int num = 0;
public void add1(String username) {
try {
if(username.equals("a")) {
num = 100;
System.out.println("a set over");
Thread.sleep(3000); //用来等待b
}else {
num = 200;
System.out.println("b set over");
}
System.out.println(username + "num = " + num); } catch (InterruptedException e) {
e.printStackTrace();
}
}
}
2.2 创建一个ThreadA类:
package edu.ymm.about_thread1; public class ThreadA extends Thread { private HasSelfPrivate numself;
public ThreadA(HasSelfPrivate numself) {
super();
this.numself = numself;
} @Override
public void run() {
super.run();
numself.add1("a ");
} }
2.3创建一个ThreadB类:
package edu.ymm.about_thread1; public class ThreadB extends Thread { private HasSelfPrivate numself;
public ThreadB(HasSelfPrivate numself) {
super();
this.numself = numself;
}
@Override
public void run() {
super.run();
numself.add1("b ");
}
}
2.4来测试一下这个例子:
package edu.ymm.about_thread1; public class Test { public static void main(String[] args) { HasSelfPrivate hPrivate = new HasSelfPrivate();
ThreadA threadA = new ThreadA(hPrivate);
threadA.start();
ThreadB threadB =new ThreadB(hPrivate);
threadB.start();
} }
结果如下:
上述就是所谓的“非线程安全”的一个例子。a的值不是我们预期的100了。要解决这种现象,只需要在a和b共同访问的方法前加上“synchronized”就可以了。
更新这个类后:
package edu.ymm.about_thread1; public class HasSelfPrivate {
private int num = 0;
synchronized public void add1(String username) {
try {
if(username.equals("a")) {
num = 100;
System.out.println("a set over");
Thread.sleep(2000); //用来等待b
}else {
num = 200;
System.out.println("b set over");
}
System.out.println(username + " num=" + num); } catch (InterruptedException e) {
e.printStackTrace();
}
}
}
再执行结果为:
所以,在两个线程访问同一个对象中的同步方法(synchronized)时一定是线程安全的。
3.多个对象多个锁
我们来改动一点:将测试中产生两个实例对象。
3.1 HasSelfPrivate类如下:
package edu.ymm.about_thread2; public class HasSelfPrivate {
private int num = 0;
synchronized public void add1(String username) {
try {
if(username.equals("a")) {
num = 100;
System.out.println("a set over");
Thread.sleep(2000); //用来等待b
}else {
num = 200;
System.out.println("b set over");
}
System.out.println(username + " num=" + num); } catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上面代码中有同步方方法add1,说明此方法应该被顺序调用。
3.2 创建一个ThreadA类:
package edu.ymm.about_thread2; public class ThreadA extends Thread { private HasSelfPrivate numself;
public ThreadA(HasSelfPrivate numself) {
super();
this.numself = numself;
} @Override
public void run() {
super.run();
numself.add1("a");
} }
3.3创建一个ThreadB类:
package edu.ymm.about_thread2; public class ThreadB extends Thread { private HasSelfPrivate numself;
public ThreadB(HasSelfPrivate numself) {
super();
this.numself = numself;
}
@Override
public void run() {
super.run();
numself.add1("b");
}
}
3.4来测试一下这个例子:
package edu.ymm.about_thread2; public class Test { public static void main(String[] args) { HasSelfPrivate hPrivate1 = new HasSelfPrivate();
HasSelfPrivate hPrivate2 = new HasSelfPrivate();
ThreadA threadA = new ThreadA(hPrivate1);
threadA.start();
ThreadB threadB =new ThreadB(hPrivate2);
threadB.start();
} }
执行结果如下:
上述示例是两个线程分别访问一个类的两个不同实例的相同名称的同步方法,效果却是异步的方式运行的。本示例由于创建了2个业务对象,在系统中产生了两个锁,所以运行结果是异步的,打印的效果就是先打印b再打印a。
关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法(函数)当作锁,所以在上面的示例中,哪个线程先执行带synchronized关键字的方法,哪个线程就持有该方法所属对象的锁Lock,那么其他线程只能呈等待状态,前提是多个线程访问的是同一个对象。
但是如果多个线程访问多个对象,则JVM会创建多个锁。
synchronized同步方法《一》的更多相关文章
- synchronized同步方法《二》
1.synchronized方法和锁对象 (1).验证线程锁的是对象 代码如下: 1.1创建一个MyObject类: package edu.ymm.about_thread4; public cla ...
- synchronized同步方法
“非线程安全”其实会在多个线程对同一个对象中的实例变量进行并发访问的时候产生,产生的后果是脏读,也就是取到的数据是被更改过的.而“线程安全”就是以获得的实例变量的值是经过同步处理的,不会出现脏读的现象 ...
- 四、java多线程核心技术——synchronized同步方法与synchronized同步快
一.synchronized同步方法 论:"线程安全"与"非线程安全"是多线程的经典问题.synchronized()方法就是解决非线程安全的. 1.方法内的变 ...
- java多线程(二)——锁机制synchronized(同步方法)
synchronized Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.当两个并发线程访问同一个对象object中 ...
- 深入理解使用synchronized同步方法和同步代码块的区别
一.代码块和方法之间的区别 首先需要知道代码块和方法有什么区别: 构造器和方法块,构造器可以重载也就是说明在创建对象时可以按照不同的构造器来创建,那么构造器是属于对象,而代码块呢他是给所有的对象初始化 ...
- 二十二 synchronized同步方法
一 Synchronized锁: 1 synchronized取得的锁都是对象锁,而不是把一段代码或方法加锁. synchronized是给该方法的实例对象加锁.如果多个线程访问的是同一个对象 的s ...
- synchronized同步方法和同步代码块的区别
同步方法默认使用this或者当前类做为锁. 同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不是整个方法. 同步方法使用synchronized修 ...
- 58、synchronized同步方法
线程安全问题 先看下面代码出现的问题: 定义一个Task类,里面有一个成员变量和一个有boolean类型参数的方法,方法内部会根据传入参数修改成员变量的值. package com.sutaoyu.T ...
- java synchronized静态同步方法与非静态同步方法,同步语句块
摘自:http://topmanopensource.iteye.com/blog/1738178 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁. 对代码进行同步控制我们可以选择同步方 ...
随机推荐
- Mysql报错java.sql.SQLException:null,message from server:"Host '27,45,38,132' is not allowed to connect
Mysql报错java.sql.SQLException:null,message from server:"Host '27,45,38,132' is not allowed to co ...
- sql存储过程算法
MSSQL执行 : exec proc_NAME ORACLE : beginproc_NAME;commit;end; 1.求素数 MSSQL; CREATE proc [dbo].[EXEC003 ...
- nlp homework 03
NLP Homework 03 --冯煜博 题目描述 (盒子和球模型)假设有3个盒子,每个盒子里装有红白两种颜色的球,盒子里的红白球有下表列出,初始状态分布. 解答 1. 给出HMM模型 \(\mu= ...
- 细数php里的那些“坑”
Part 1 Grammer 尽管PHP的语法已经很松散,写起来很“爽”.但是对于学过 Java 的“完全面向对象程序员“来说,PHP程序设计语言里,还是有一些的坑的.下面请让我来盘点一下. Pars ...
- mustache 模板使用
//一 ,基本使用 <!DOCTYPE html><html ng-app="myApp"><head lang="en"> ...
- EXP7 网络欺诈技术防范(修改版)
实践内容 本实践的目标理解常用网络欺诈背后的原理,以提高防范意识,并提出具体防范方法. 1.简单应用SET工具建立冒名网站 2.ettercap DNS spoof 3.结合应用两种技术,用DNS s ...
- NOIP 2016 蚯蚓 (luogu 2827 & uoj 264) - 鬼畜的优化
题目描述 本题中,我们将用符号\lfloor c \rfloor⌊c⌋表示对c向下取整,例如:\lfloor 3.0 \rfloor= \lfloor 3.1 \rfloor=\lfloor 3.9 ...
- python --- 08 文件操作
一. 文件 f = open(文件路径,mode = '模式',encoding = '编码格式') 1.基础 ① 读写时,主要看光标的位置 ②操作完成要写 f.close( ) f.flu ...
- 第一次怎么把本地git仓库的内容push到远程仓库?
使用git push origin <分支名> -f 这种方式可以用本地仓库的内容覆盖远程仓库.
- Django框架(八) Django之ORM数据库操作
创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关系( ...