您的位置:首页 > 其它

多线程基础知识总结(二)

2018-01-26 17:59 302 查看

全文概要

本文主要介绍JAVA线程中synchronized关键字的用法。对于synchronized关键字主要包含以下几点:

当一个线程访问某一个对象synchronized修饰的非静态方法或者代码块时,其他线程不允许访问该对象synchronized修饰的相同的方法或者代码块;
当一个线程访问某一个对象synchronized修饰的非静态方法或者代码块时,其他线程不允许访问该对象synchronized修饰的其他的非静态方法或者代码块;

当一个线程访问某一个对象synchronized修饰的方法或者代码块时,其他线程允许访问该对象的非synchronized修饰的方法或者代码块;
当一个线程访问某一个对象synchronized修饰的方法或者代码块时,其他线程允许访问其他对象synchronized修饰的非静态方法或者代码块;

当一个线程访问某一个对象synchronized修饰的非静态方法或者代码块时,其他线程允许访问该对象synchronized修饰的静态方法或者代码块;

当一个线程访问同一个字节码对象的synchronized修饰的静态方法或者代码块时,其他线程不允许访问该节码对象的所有的synchronized修饰的静态方法或者代码块

synchronized关键字用法

验证第一点

代码案例
package com.tml.javaCore.thread.sync;

/**
* <p>多线程
* @author Administrator
*
*/
public class SynchronizedDemo1 {
public static void main(String[] args) {
SynchronizedDemo1 demo  = new  SynchronizedDemo1();

Thread t1 = new  Thread(new Runnable() {
public void run() {
demo.print();
}
}, "t1");

Thread t2 = new  Thread(new Runnable() {
public void run() {
demo.print();
}
}, "t2");

t1.start();
t2.start();

}

private synchronized void print() {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

4000
}
}

输出结果
 t1 is running ....!
 t1 is running ....!
 t1 is running ....!
 t1 is running ....!
 t1 is running ....!
 t2 is running ....!
 t2 is running ....!
 t2 is running ....!
 t2 is running ....!
 t2 is running ....!

结果说明
 线程1和线程2都是调用SynchronizedDemo1对象的print()方法,线程1执行时,线程2阻塞。

验证第二点

代码案例
package com.tml.javaCore.thread.sync;

/**
* <p>多线程
* @author Administrator
*
*/
public class SynchronizedDemo2 {
public static void main(String[] args) {
SynchronizedDemo2 demo  = new  SynchronizedDemo2();

Thread t1 = new  Thread(new Runnable() {
public void run() {
demo.print();
}
}, "t1");

Thread t2 = new  Thread(new Runnable() {
public void run() {
demo.read("hello world!");
}
}, "t2");

t1.start();
t2.start();

}

private synchronized void print() {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

private synchronized  void read(String name) {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is reading :" + name );
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}

输出结果
 t1 is running ....!
 t1 is running ....!
 t1 is running ....!
 t1 is running ....!
 t1 is running ....!
 t2 is reading :hello world!
 t2 is reading :hello world!
 t2 is reading :hello world!
 t2 is reading :hello world!
 t2 is reading :hello world!

结果说明
 线程1调用demo的print()方法,线程2调用demo的read()方法,虽然方法不同,但都是公用一个同步锁,所以线程1执行时,线程2阻塞。

验证第三点

代码案例
package com.tml.javaCore.thread.sync;

/**
* <p>多线程
* @author Administrator
*
*/
public class SynchronizedDemo3 {
public static void main(String[] args) {
SynchronizedDemo3 demo  = new  SynchronizedDemo3();

Thread t1 = new  Thread(new Runnable() {
public void run() {
demo.print();
}
}, "t1");

Thread t2 = new  Thread(new Runnable() {
public void run() {
demo.write("hello world!");
}
}, "t2");

t1.start();
t2.start();

}

private  void print() {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

private synchronized void write(String name) {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is writing :" + name );
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}

输出结果
 t1 is running ....!
 t2 is writing :hello world!
 t2 is writing :hello world!
 t1 is running ....!
 t2 is writing :hello world!
 t1 is running ....!
 t1 is running ....!
 t2 is writing :hello world!
 t2 is writing :hello world!
 t1 is running ....!

结果说明
 print()方法为非同步方法,不会占用对象锁,所以线程1和线程2同时执行。

验证第四点

代码案例
package com.tml.javaCore.thread.sync;

/**
* <p>多线程
* @author Administrator
*
*/
public class SynchronizedDemo4 {
public static void main(String[] args) {
SynchronizedDemo4 demo  = new  SynchronizedDemo4();
SynchronizedDemo4 demo1  = new  SynchronizedDemo4();

Thread t1 = new  Thread(new Runnable() {
public void run() {
demo.print();
}
}, "t1");

Thread t2 = new  Thread(new Runnable() {
public void run() {
demo1.print();
}
}, "t2");

t1.start();
t2.start();

}

private synchronized void print() {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

}

输出结果
 t2 is running ....!
 t1 is running ....!
 t2 is running ....!
 t1 is running ....!
 t2 is running ....!
 t1 is running ....!
 t1 is running ....!
 t2 is running ....!
 t2 is running ....!
 t1 is running ....!

结果说明
 线程1和线程2的对象锁不一样,所以线程1和线程2同时执行。

验证第五点

代码案例
package com.tml.javaCore.thread.sync;

/**
* <p>多线程
* @author Administrator
*
*/
public class SynchronizedDemo5 {
public static void main(String[] args) {
SynchronizedDemo5 demo  = new  SynchronizedDemo5();

Thread t1 = new  Thread(new Runnable() {
public void run() {
/*
* 调用非静态方法
*/
demo.print();

}
}, "t1");

Thread t2 = new  Thread(new Runnable() {
public void run() {
demo.staticPrint();//用对象调用静态方法,不规范,会有警告,建议用下面的方法
//SynchronizedDemo5.staticPrint();
}
}, "t2");

t1.start();
t2.start();

}

private synchronized void print() {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is print running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

/*
* 静态同步方法
*/
private synchronized static void staticPrint(){
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is staticPrint running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

输出结果
 t2 is staticPrint running
....!
 t1 is print running ....!
 t2 is staticPrint running ....!
 t1 is print running ....!
 t1 is print running ....!
 t2 is staticPrint running ....!
 t2 is staticPrint running ....!
 t1 is print running ....!
 t1 is print running ....!
 t2 is staticPrint running ....!

结果说明
 线程1和线程2虽然都是调用demo对象的方法,但是print()为非静态同步方法,而staticPrint()为静态同步方法,根本原因
是对象锁不一样。非静态方法的同步锁为demo,而静态方法的同步锁为SynchronizedDemo5.class

验证第六点

代码案例
package com.tml.javaCore.thread.sync;

/**
* <p>多线程
* @author Administrator
*
*/
public class SynchronizedDemo6 {
public static void main(String[] args) {

Thread t1 = new  Thread(new Runnable() {
public void run() {
SynchronizedDemo6.staticPrint();

}
}, "t1");

Thread t2 = new  Thread(new Runnable() {
public void run() {
SynchronizedDemo6.staticPrint1();
}
}, "t2");

t1.start();
t2.start();

}

@SuppressWarnings("unused")
private synchronized void print() {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is print running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

@SuppressWarnings("unused")
private  void print1() {
synchronized (this) {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is print1 running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

/*
* 静态同步方法
*/
private synchronized static void staticPrint(){
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is staticPrint running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

private  static void staticPrint1(){
/*
* 静态同步代码块
*/
synchronized (SynchronizedDemo6.class) {
for(int i=0;i<5;i++){
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName() + " is staticPrint1 running ....!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

}

输出结果
 t1 is staticPrint running ....!
 t1 is staticPrint running ....!
 t1 is staticPrint running ....!
 t1 is staticPrint running ....!
 t1 is staticPrint running ....!
 t2 is staticPrint1 running ....!
 t2 is staticPrint1 running ....!
 t2 is staticPrint1 running ....!
 t2 is staticPrint1 running ....!
 t2 is staticPrint1 running ....!

结果说明
 对于静态方法,他的同步锁是该类的字节码对象,该对象在java内存中只有一份,例如,staticPrint()和staticPrint1()方法的同步锁一样。而非静态方法可以使用this来作为同步锁,this表示当前对象。例如,print()和print1()方法的同步锁一样。很多单例方法都使用字节码对象锁,确保该类只有一个实例。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: