如果大家想了解synchronized的信息,可以看我的另外一篇博客:https://blog.csdn.net/killerofjava/article/details/103374409
1.两个线程同时访问一个对象的同步方法。
public class SynchronizedObjectMethod3 implements Runnable {
static SynchronizedObjectMethod3 soMethod=new SynchronizedObjectMethod3();
@Override
public void run() {
method();
}
public synchronized void method(){
System.out.println("我的对象锁的方法修饰形式,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread thread01 = new Thread(soMethod);
Thread thread02 = new Thread(soMethod);
thread01.start();
thread02.start();
while (thread01.isAlive() || thread02.isAlive()){
}
System.out.println("finished");
}
}
结果:
原因:因为这两个线程用的都是同一个runnable实例,所以它们拿的是同一把对象锁,既然是同一把锁那么它们自然就窜行执行。
2.两个线程访问的是两个对象的同步方法。
public class SynchronizedObjectMethod3 implements Runnable {
static SynchronizedObjectMethod3 soMethod1=new SynchronizedObjectMethod3();
static SynchronizedObjectMethod3 soMethod2=new SynchronizedObjectMethod3();
@Override
public void run() {
method();
}
public synchronized void method(){
System.out.println("我的对象锁的方法修饰形式,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread thread01 = new Thread(soMethod1);
Thread thread02 = new Thread(soMethod2);
thread01.start();
thread02.start();
while (thread01.isAlive() || thread02.isAlive()){
}
System.out.println("finished");
}
}
结果:
原因:因为这两个线程用的不是同一个runnable实例,所以它们拿的不是同一把对象锁,既然不是同一把锁,那么它们自然就并行执行。
3.两个线程访问的是synchronized的静态方法。
public class SynchronizedClassStatic4 implements Runnable{
static SynchronizedClassStatic4 instance1 = new SynchronizedClassStatic4();
static SynchronizedClassStatic4 instance2 = new SynchronizedClassStatic4();
@Override
public void run() {
method();
}
public static synchronized void method(){
System.out.println("我是类锁的第一种形式:static形式,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread thread01 = new Thread(instance1);
Thread thread02 = new Thread(instance2);
thread01.start();
thread02.start();
while (thread01.isAlive() || thread02.isAlive()){
}
System.out.println("finished");
}
}
结果:
原因:因为访问的方法被synchronized和static关键字修饰,所以不管是不是用的是同一个runnable实例,它们获得的都是同一把类锁,自然是窜行执行。
4.同时访问同步方法和非同步方法。
public class SynchronizedYesOrNo6 implements Runnable {
static SynchronizedYesOrNo6 instance = new SynchronizedYesOrNo6();
@Override
public void run() {
if ("Thread-0".equals(Thread.currentThread().getName())){
method1();
}else{
method2();
}
}
public synchronized void method1(){
System.out.println("我加锁的方法,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public void method2(){
System.out.println("我没加锁的方法,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread thread01 = new Thread(instance);
Thread thread02 = new Thread(instance);
thread01.start();
thread02.start();
while (thread01.isAlive() || thread02.isAlive()){
}
System.out.println("finished");
}
}
结果:
原因:因为没有加锁的方法是可以被任何线程访问的,所以它们并行执行。
5.访问同一个对象的不同的普通同步方法。
public class SynchronizedDifferentMethod7 implements Runnable {
static SynchronizedDifferentMethod7 instance = new SynchronizedDifferentMethod7();
@Override
public void run() {
if ("Thread-0".equals(Thread.currentThread().getName())){
method1();
}else{
method2();
}
}
public synchronized void method1(){
System.out.println("我加锁的方法1,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public synchronized void method2(){
System.out.println("我加锁的方法2,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread thread01 = new Thread(instance);
Thread thread02 = new Thread(instance);
thread01.start();
thread02.start();
while (thread01.isAlive() || thread02.isAlive()){
}
System.out.println("finished");
}
}
结果:
原因:因为用的是同一个runnable实例,所以这两个普通的同步方法用的都是同一把对象锁,自然它们都是窜行执行。
6.同时访问静态synchronized和非synchronized方法。
public class SynchronizedStaticAndNormal8 implements Runnable {
static SynchronizedStaticAndNormal8 instance = new SynchronizedStaticAndNormal8();
@Override
public void run() {
if ("Thread-0".equals(Thread.currentThread().getName())){
method1();
}else{
method2();
}
}
public static synchronized void method1(){
System.out.println("我静态加锁的方法1,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public synchronized void method2(){
System.out.println("我非静态加锁的方法2,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread thread01 = new Thread(instance);
Thread thread02 = new Thread(instance);
thread01.start();
thread02.start();
while (thread01.isAlive() || thread02.isAlive()){
}
System.out.println("finished");
}
}
结果:
原因;因为获得的锁不同,一个获得的是类锁,二另一个获得的是对象锁,所以它们会并行执行。
7.方法抛出异常后,会释放锁。
public class SynchronizedException9 implements Runnable {
static SynchronizedException9 instance = new SynchronizedException9();
@Override
public void run() {
if ("Thread-0".equals(Thread.currentThread().getName())){
method1();
}else{
method2();
}
}
public synchronized void method1(){
System.out.println("我加锁的方法1,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int i=8/0;
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public synchronized void method2(){
System.out.println("我加锁的方法2,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread thread01 = new Thread(instance);
Thread thread02 = new Thread(instance);
thread01.start();
thread02.start();
while (thread01.isAlive() || thread02.isAlive()){
}
System.out.println("finished");
}
}
结果:
原因:被synchronized关键字修饰的方法在抛出异常后,jvm会自动的帮我们释放锁,不需要我们手动释放锁。我们可以看到在method1()方法抛出异常后,method2()方法立马执行了。