1、两个线程同时访问一个对象的同步方法
public class SynchronizedObjectMethod implements Runnable {
private static SynchronizedObjectMethod synchronizedObjectMethod = new
SynchronizedObjectMethod();
@Override
public void run() {
test();
}
public synchronized void test(){
System.out.println("test()方法运行开始" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test()方法运行结束" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t1 = new Thread(synchronizedObjectMethod);
Thread t2 = new Thread(synchronizedObjectMethod);
t1.start();
t2.start();
//线程的isAlive()方法的功能是判断当前线程是否处于活动状态(就绪状态或者运行状态)
//下面的循环会在两个线程都运行结束后 结束
while(t1.isAlive() || t2.isAlive()){
}
System.out.println("程序运行结束");
}
}
代码运行结果:
test()方法运行开始Thread-0
test()方法运行结束Thread-0
test()方法运行开始Thread-1
test()方法运行结束Thread-1
程序运行结束
2、两个线程访问的是两个对象的同步方法
public class SynchronizedObjectMethod implements Runnable {
private static SynchronizedObjectMethod instance1 = new
SynchronizedObjectMethod();
private static SynchronizedObjectMethod instance2 = new
SynchronizedObjectMethod();
@Override
public void run() {
test();
}
public synchronized void test(){
System.out.println("test()方法运行开始" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test()方法运行结束" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
//线程的isAlive()方法的功能是判断当前线程是否处于活动状态(就绪状态或者运行状态)
//下面的循环会在两个线程都运行结束后 结束
while(t1.isAlive() || t2.isAlive()){
}
System.out.println("程序运行结束");
}
}
代码运行结果:
test()方法运行开始Thread-0
test()方法运行开始Thread-1
test()方法运行结束Thread-0
test()方法运行结束Thread-1
程序运行结束
如果两个线程访问的是两个对象的同步方法,那么这两个线程的运行时互不影响的。
3、两个线程访问的是synchronized的静态方法
public class SynchronizedClassStatic implements Runnable {
private static SynchronizedClassStatic instance1 = new SynchronizedClassStatic();
private static SynchronizedClassStatic instance2 = new SynchronizedClassStatic();
@Override
public void run() {
test();
}
public synchronized static void test(){
System.out.println("test()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test()方法运行结束\t" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
//线程的isAlive()方法的功能是判断当前线程是否处于活动状态(就绪状态或者运行状态)
//下面的循环会在两个线程都运行结束后 结束
while(t1.isAlive() || t2.isAlive()){
}
System.out.println("程序运行结束");
}
}
代码运行结果:
test()方法运行开始 Thread-0
test()方法运行结束 Thread-0
test()方法运行开始 Thread-1
test()方法运行结束 Thread-1
程序运行结束
4、同时访问同步方法与非同步方法
synchronized关键字只作用于被修饰的方法或代码块上,不会影响到其他没有被synchronized修饰的方法或代码。
public class SynchronizedYesAndNo implements Runnable {
private static SynchronizedYesAndNo instance = new SynchronizedYesAndNo();
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
test0();
} else {
test1();
}
}
public synchronized void test0(){
System.out.println("synchronized test0()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronized test0()方法运行结束\t" + Thread.currentThread().getName());
}
public void test1(){
System.out.println("test1()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("test1()方法运行结束\t" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
//线程的isAlive()方法的功能是判断当前线程是否处于活动状态(就绪状态或者运行状态)
//下面的循环会在两个线程都运行结束后 结束
while(t1.isAlive() || t2.isAlive()){
}
System.out.println("程序运行结束");
}
}
代码运行结果:
synchronized test0()方法运行开始 Thread-0
test1()方法运行开始 Thread-1
synchronized test0()方法运行结束 Thread-0
test1()方法运行结束 Thread-1
程序运行结束
5、访问同一个对象的不同的普通同步方法
就同一个实例而言,多线程在访问该实例的不同的普通同步方法的时候,多线程之间会顺序执行,而不会同时执行,因为synchronized虽然修饰的方法不同,但是他们的锁对象(this)确是同一个,而一个锁在同一时刻只能被一个线程占用。
public class SynchronizedDiffMethod implements Runnable {
private static SynchronizedDiffMethod instance = new SynchronizedDiffMethod();
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
test0();
} else {
test1();
}
}
public synchronized void test0(){
System.out.println("synchronized test0()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronized test0()方法运行结束\t" + Thread.currentThread().getName());
}
public synchronized void test1(){
System.out.println("synchronized test1()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronized test1()方法运行结束\t" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
//线程的isAlive()方法的功能是判断当前线程是否处于活动状态(就绪状态或者运行状态)
//下面的循环会在两个线程都运行结束后 结束
while(t1.isAlive() || t2.isAlive()){
}
System.out.println("程序运行结束");
}
}
代码运行结果:
synchronized test0()方法运行开始 Thread-0
synchronized test0()方法运行结束 Thread-0
synchronized test1()方法运行开始 Thread-1
synchronized test1()方法运行结束 Thread-1
程序运行结束
6、同时访问静态synchronized和非静态synchronized方法
两个线程同时访问一个实例的静态synchronized和非静态synchronized方法的时候,两个线程是同时执行的,互不干扰的,原因就在于锁对象不是同一个,一个锁是当前实例对象,一个锁是实例对应类的Class对象。
public class SynchronizedStaticAndNormal implements Runnable {
private static SynchronizedStaticAndNormal instance = new SynchronizedStaticAndNormal();
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
test0();
} else {
test1();
}
}
public synchronized static void test0(){
System.out.println("synchronized static test0()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronized static test0()方法运行结束\t" + Thread.currentThread().getName());
}
public synchronized void test1(){
System.out.println("synchronized test1()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronized test1()方法运行结束\t" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
//线程的isAlive()方法的功能是判断当前线程是否处于活动状态(就绪状态或者运行状态)
//下面的循环会在两个线程都运行结束后 结束
while(t1.isAlive() || t2.isAlive()){
}
System.out.println("程序运行结束");
}
}
代码运行结果:
synchronized static test0()方法运行开始 Thread-0
synchronized test1()方法运行开始 Thread-1
synchronized test1()方法运行结束 Thread-1
synchronized static test0()方法运行结束 Thread-0
程序运行结束
7、方法抛出异常后,会释放锁
public class SynchronizedException implements Runnable {
private static SynchronizedException instance = new SynchronizedException();
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
test0();
} else {
test1();
}
}
public synchronized void test0(){
System.out.println("synchronized static test0()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
throw new RuntimeException();
//System.out.println("synchronized static test0()方法运行结束\t" + Thread.currentThread().getName());
}
public synchronized void test1(){
System.out.println("synchronized test1()方法运行开始\t" + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("synchronized test1()方法运行结束\t" + Thread.currentThread().getName());
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
//线程的isAlive()方法的功能是判断当前线程是否处于活动状态(就绪状态或者运行状态)
//下面的循环会在两个线程都运行结束后 结束
while(t1.isAlive() || t2.isAlive()){
}
System.out.println("程序运行结束");
}
}
代码运行结果:
synchronized static test0()方法运行开始 Thread-0
Exception in thread "Thread-0" synchronized test1()方法运行开始 Thread-1
java.lang.RuntimeException
at com.bxp.thread.SynchronizedException.test0(SynchronizedException.java:21)
at com.bxp.thread.SynchronizedException.run(SynchronizedException.java:8)
at java.lang.Thread.run(Thread.java:748)
synchronized test1()方法运行结束 Thread-1
程序运行结束
总结:
1)一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待(对应第1、5种情况)
2)每个实例都对应的有自己的一把锁,不同实例之间是互不影响的。例外,锁对象是*.class以及synchronized修饰的是static方法的时候,所有对象共用同一把锁(对应第2、3、4、6种情况)
3)无论方法是正常执行完毕还是方法抛出异常,都会释放锁(对应第7种情况)
补充:当线程进入到一个被synchronized修饰的方法A,A方法调用了没有被synchronized修饰的方法B,线程在运行B方法的时候,是没有线程安全的,此时其他的线程也可以调用方法B,因为方法B没有被synchronized修饰,不是线程安全的。