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 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁. 对代码进行同步控制我们可以选择同步方 ...
随机推荐
- 作为phper既然了解共享内存函数shmop的使用方法,那么就必须要了解一下信号量是什么,以及信号量使用的代码案例
在单独的一个PHP进程中读写.创建.删除共享内存方面上你应该没有问题了.但是实际运行中不可能只是一个PHP进程在运行中.如果在多个进程的情况下你还是沿用单个进程的处理方法,你一定会碰到问题--著名的并 ...
- django模板-自定义标签、过滤器
自定义标签或者过滤器的步骤 ①将要创建自定义标签或过滤器的app加入settings文件的installed_apps中 ②在app中创建templatetags目录,类型为包即packages ③在 ...
- Apache2.4反向代理设置
一.配置方向代理 1,放开虚拟主机(反向代理)模块,在httpd.conf中把下三行配置放开: LoadModule proxy_module modules/mod_proxy.so LoadMod ...
- 使用maven profile实现多环境配置相关打包
项目开发需要有多个环境,一般为开发,测试,预发,正式4个环境,通过maven可以实现按不同环境进行打包部署,命令为: mvn package -P dev 在eclipse中可以右击选项run con ...
- 值得收藏的8个Web端组件库
值得收藏的8个Web端组件库 Ant Design 介绍:一个服务于企业级产品的设计体系,基于『确定』和『自然』的设计价值观和模块化的解决方案,让设计者专注于更好的用户体验. 组件库地址:https: ...
- python识别图片生成字符模式
此python文件来自D7哥, 放在这里备份. 用法 python3 PIL\&argparse.py 1.jpg -o test.txt --width 300 --height 300 p ...
- python简说(二十四)发送网络请求
一.get,post请求import requestsurl='http://127.0.0.1:8999/api/upload'# data = {'username':'testuser1','p ...
- python简说(十一)os模块
import osres = os.listdir('/Users/nhy/Desktop') #列出某个目录下的所有文件# os.remove()# os.rename()# os.mkdir(r' ...
- 记一次gitlab添加用户收不到邮件的解决办法
之前再gitlab服务器上创建账号可以正常收到邮件,最近就收不到,查了gitlab的配置以及postfix服务都没有问题,后来查看了发信25端口,发现该25端口并没有开启(postfix已经开启),提 ...
- MS11-050安全漏洞
IE浏览器渗透攻击--MS11050安全漏洞 实验前准备 1.两台虚拟机,其中一台为kali,一台为windows xp sp3(包含IE7). 2.设置虚拟机网络为NAT模式,保证两台虚拟机可以相互 ...