1、两个线程同时访问一个对象的同步方法
public class SynchroizedObject extends Thread{
static SynchroizedObject instance = new SynchroizedObject();
public static void main(String []args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
}
@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()+"运行结束");
}
}
运行结果:
我的对象锁的方法修饰符形式,我叫Thread-1
Thread-1运行结束
我的对象锁的方法修饰符形式,我叫Thread-2
Thread-2运行结束
同一个实例使用同一把锁,两个线程使用同一把锁,必然有一个处于等待,一个线程执行完成,另一个线程才可以执行。
2、两个线程访问的是两个对象的同步方法
public class SynchroizedObject2 extends Thread{
static SynchroizedObject2 instance1 = new SynchroizedObject2();
static SynchroizedObject2 instance2 = new SynchroizedObject2();
public static void main(String []args) {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
}
@Override
public void run() {
synchronized (this) {
System.out.println("我的对象锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
}
}
运行结果:
我的对象锁的方法修饰符形式,我叫Thread-2
我的对象锁的方法修饰符形式,我叫Thread-3
Thread-2运行结束
Thread-3运行结束
结果线程同时开始,同时结束,之间不会受干扰,因为对象不是同一个,所以不会受干扰。
3、两个线程访问的是synchronize 的静态方法
public class SynchroizedObject3 extends Thread{
static SynchroizedObject3 instance1 = new SynchroizedObject3();
static SynchroizedObject3 instance2 = new SynchroizedObject3();
public static void main(String []args) {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
}
@Override
public void run() {
method();
}
public static synchronized void method () {
System.out.println("我的对象锁的方法修饰符形式,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
}
运行结果
我的对象锁的方法修饰符形式,我叫Thread-2
Thread-2运行结束
我的对象锁的方法修饰符形式,我叫Thread-3
Thread-3运行结束
只要方法是静态的,锁对应的就是一把,所以线程是一个执行完成,再去执行下一个线程。
4、同时访问同步方法与非同步方法
public class SynchroizedObject4 implements Runnable {
static SynchroizedObject4 instance = new SynchroizedObject4();
public static void main(String []args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
}
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) {
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()+"运行结束");
}
}
运行结果
我的加锁的方法修饰符形式,我叫Thread-0
我的没加锁的方法修饰符形式,我叫Thread-1
Thread-1运行结束
Thread-0运行结束
线程0和线程1几乎同时开始同时结束,synchronized 关键字只作用于指定的method1方法中,没有加上synchronized 这个关键字方法,不受影响,不会由于其他方法加上synchronized 而受到影响。非同步方法不受到影响。
5、访问一个对象的不同的普通同步方法
public class SynchroizedObject5 implements Runnable {
static SynchroizedObject5 instance = new SynchroizedObject5();
public static void main(String []args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
}
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) {
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 synchronized void method2() {
System.out.println("我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
}
运行结果
我叫Thread-0
Thread-0运行结束
我叫Thread-1
Thread-1运行结束
同一个实例中,这两个方法没有办法同时运行,会出现串行的情况。
6、同时访问静态synchronize和非静态synchronize方法
public class SynchroizedObject6 implements Runnable {
static SynchroizedObject6 instance = new SynchroizedObject6();
public static void main(String []args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
}
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) {
method1();
} else {
method2();
}
}
public synchronized static void method1() {
System.out.println("我是静态加锁方法,我叫"+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("非静态加锁方法,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
}
运行结果
我是静态加锁方法,我叫Thread-0
非静态加锁方法,我叫Thread-1
Thread-0运行结束
Thread-1运行结束
运行结果几乎同时运行,同时结束,所指定的锁对象不是同一个锁,所以可以同时运行。
7、方法抛异常,会释放锁
方法抛异常后,会释放锁。展示不抛出异常前和抛出异常后的对比:一旦抛出了异常,第二个线程会立刻进入同步方法,意味着锁已经释放。
public class SynchroizedObject7 implements Runnable {
static SynchroizedObject7 instance = new SynchroizedObject7();
public static void main(String []args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
}
@Override
public void run() {
if (Thread.currentThread().getName().equals("Thread-0")) {
method1();
} else {
method2();
}
}
public synchronized void method1() {
System.out.println(" 我是静态加锁方法,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
throw new RuntimeException();
// System.out.println(Thread.currentThread().getName()+"运行结束");
}
public synchronized void method2() {
System.out.println(" 非静态加锁方法,我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
}
运行结果
我是静态加锁方法,我叫Thread-0
非静态加锁方法,我叫Thread-1
Exception in thread "Thread-0" java.lang.RuntimeException
at com.test5.SynchroizedObject7.method1(SynchroizedObject7.java:39)
at com.test5.SynchroizedObject7.run(SynchroizedObject7.java:25)
at java.lang.Thread.run(Thread.java:748)
Thread-1运行结束
抛出异常之后,不需要手动手动释放锁,由jvm进行释放锁。