synchronized互斥锁实例解析
Posted amunamuna
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了synchronized互斥锁实例解析相关的知识,希望对你有一定的参考价值。
目录
java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁。线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁。获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法。
java内置锁是一个互斥锁。
对象锁是用于对象实例方法,或者一个对象实例上的
类锁是用于类的静态方法或者一个类的class对象上的。
synchronized互斥锁实例解析
1、互斥锁基础使用:防止多个线程访问对象的synchronized方法。
只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。
1.1、不加互斥锁时
public class MyThread {
public static void main(String[] args) {
MyThread s = new MyThread();
s.thread();
}
public void thread() {
final Printer p = new Printer();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
p.print("1111111111");
} catch (Exception e) {
}
}
}
}, "t1").start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
p.print("2222222222");
} catch (Exception e) {
}
}
}
}, "t2").start();
}
class Printer {
//synchronized
public void print(String str) {
// synchronized(this){
for (int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(i));
}
System.out.println();
System.out.println("上面执行的是线程:" + Thread.currentThread().getName());
// }
}
}
}
输出结果片断:
1111111111
上面执行的是线程:t1
2222222222
上面执行的是线程:t2
1111111111
上面执行的是线程:t1
2222222222
上面执行的是线程:t2
11122222221111111222
上面执行的是线程:t2
上面执行的是线程:t1
2111222222222
上面执行的是线程:t2
1111111
上面执行的是线程:t1
2222222222
上面执行的是线程:t2
1111111111
上面执行的是线程:t1
12111111111222222222
上面执行的是线程:t2
上面执行的是线程:t1
1111111111
上面执行的是线程:t1
2222222222
上面执行的是线程:t2
1.2、加互斥锁后
package cn.itcast_01_mythread.thread.thread;
/*
* 线程安全问题
*/
public class MyThread {
public static void main(String[] args) {
MyThread s=new MyThread();
s.thread();
}
public void thread(){
final Printer p=new Printer();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try{
Thread.sleep(10);
p.print("1111111111");
}catch(Exception e){
}
}
}
},"t1").start();
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try{
Thread.sleep(10);
p.print("2222222222");
}catch(Exception e){
}
}
}
},"t2").start();
}
class Printer{
//synchronized
public synchronized void print(String str){
// synchronized(this){
for(int i=0;i<str.length();i++){
System.out.print(str.charAt(i));
}
System.out.println();
System.out.println("上面执行的是线程:"+Thread.currentThread().getName());
// }
}
}
}
输出结果:不会出现错位位置
2222222222
上面执行的是线程:t2
1111111111
上面执行的是线程:t1
2222222222
上面执行的是线程:t2
1111111111
上面执行的是线程:t1
2222222222
上面执行的是线程:t2
1111111111
上面执行的是线程:t1
2222222222
上面执行的是线程:t2
1111111111
上面执行的是线程:t1
2222222222
上面执行的是线程:t2
1111111111
2、脏读
2.1、不加锁
2.1.1、例子1,两个方法都不加锁
package cn.itcast_01_mythread.thread.thread;
/*
* 脏读
*/
public class Dirty_read_4 {
private String weibo_name = "angel" ;
private String weibo_sex = "女" ;
//synchronized
public void setValue(String weibo_name , String weibo_sex){
this.weibo_name = weibo_name ;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.weibo_sex = weibo_sex ;
System.out.println("setValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
public void getValue(){
System.out.println("getValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
public static void main(String[] args) throws InterruptedException {
final Dirty_read_4 dr = new Dirty_read_4();
Thread t1 = new Thread(new Runnable() {
public void run() {
dr.setValue("huangxiaoming" , "男");
}
}) ;
t1.start();
Thread.sleep(1000);
dr.getValue();
}
}
输出结果:顺序混乱
getValue---------weibo_name :huangxiaoming-- weibo_sex : 女
setValue---------weibo_name :huangxiaoming-- weibo_sex : 男
2.1.2、例子1,getValue不加锁
package cn.itcast_01_mythread.thread.thread;
/*
* 脏读
*/
public class Dirty_read_4 {
private String weibo_name = "angel" ;
private String weibo_sex = "女" ;
//synchronized
public synchronized void setValue(String weibo_name , String weibo_sex){
this.weibo_name = weibo_name ;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.weibo_sex = weibo_sex ;
System.out.println("setValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
//TODO synchronized
public void getValue(){
System.out.println("getValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
public static void main(String[] args) throws InterruptedException {
final Dirty_read_4 dr = new Dirty_read_4();
Thread t1 = new Thread(new Runnable() {
public void run() {
dr.setValue("huangxiaoming" , "男");
}
}) ;
t1.start();
Thread.sleep(1000);
dr.getValue();
}
}
输出结果:顺序混乱
getValue---------weibo_name :huangxiaoming-- weibo_sex : 女
setValue---------weibo_name :huangxiaoming-- weibo_sex : 男
2.2、加锁后
能够保证,执行顺序按照main方法的调用顺序依次执行。
sleep是带锁沉睡。
package cn.itcast_01_mythread.thread.thread;
/*
* 脏读
*/
public class Dirty_read_4 {
private String weibo_name = "angel" ;
private String weibo_sex = "女" ;
//synchronized
public synchronized void setValue(String weibo_name , String weibo_sex){
this.weibo_name = weibo_name ;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.weibo_sex = weibo_sex ;
System.out.println("setValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
//TODO synchronized
public synchronized void getValue(){
System.out.println("getValue---------weibo_name :" + weibo_name + "-- weibo_sex : "+weibo_sex);
}
public static void main(String[] args) throws InterruptedException {
final Dirty_read_4 dr = new Dirty_read_4();
Thread t1 = new Thread(new Runnable() {
public void run() {
dr.setValue("huangxiaoming" , "男");
}
}) ;
t1.start();
Thread.sleep(1000);
dr.getValue();
}
}
输出结果:
setValue---------weibo_name :huangxiaoming-- weibo_sex : 男
getValue---------weibo_name :huangxiaoming-- weibo_sex : 男
以上是关于synchronized互斥锁实例解析的主要内容,如果未能解决你的问题,请参考以下文章
ReentrantLock锁与内置锁synchronized