1.两个线程同时访问一个对象的同步方法
/**
* @author sxylml
* @Date : 2019/2/26 09:29
* @Description:
* 两个线程同时访问一个对象的同步方法
*/
public class SynchronizedObjectMethod implements Runnable {
@Override
public void run() {
method();
}
/**
* 默认以this 对象作为锁。
*/
public synchronized void method() {
System.out.println("对象锁的方法修饰符形式,我叫:" + Thread.currentThread().getName());
try {
System.out.println(Thread.currentThread().getName() + " 休眠3秒");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "运行结束");
}
public static void main(String[] args) {
Long startTime = System.currentTimeMillis();
Runnable instance = new SynchronizedObjectMethod();
// 同一个实例的两个不同线程,访问同一个被synchronized 修饰的方法
// 争抢的是同一把锁 ,所以需要等待
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
Long endTime = System.currentTimeMillis();
System.out.println("整个程序运行结束! 用时" + (endTime - startTime));
}
}
需要争抢同一把锁this 所以顺序执行

2.两个线程访问的是两个对象的同步方法
/**
* @author sxylml
* @Date : 2019/2/26 10:58
* @Description: 两个线程访问的是两个对象的同步方法
*/
public class SynchronizedTwoThreadToTwoObject implements Runnable {
static Runnable instance1 = new SynchronizedTwoThreadToTwoObject();
static Runnable instance2 = new SynchronizedTwoThreadToTwoObject();
@Override
public void run() {
// 当前对象作为锁
synchronized (this) {
String threadName = Thread.currentThread().getName();
System.out.println("我是对象锁的代码块形式。我叫" + threadName);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是对象锁的代码块形式。我叫" + threadName + "运行结束!");
}
}
public static void main(String[] args) {
Long startTime = System.currentTimeMillis();
// 两个线程访问的是两个对象的同步方法,同时开始,同时结束,可以理解并行执行的
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
while (t1.isAlive() || t2.isAlive()) {
}
Long endTime = System.currentTimeMillis();
System.out.println("整个程序运行结束! 用时" + (endTime - startTime));
}
}

并行处理,不受干扰,锁的对象不是同一个
3.两个线程访问的是Synchronized的静态方法
/**
* @author sxylml
* @Date : 2019/2/26 10:04
* @Description: 类锁的一种形式,static 形式
*
* 两个线程访问的是Synchronized的静态方法
*/
public class SynchronizedClassStatic implements Runnable {
static Runnable instatnce1 = new SynchronizedClassStatic();
static Runnable instatnce2 = new SynchronizedClassStatic();
public static synchronized void method() {
System.out.println("我是类锁的第一种形式:static 形式,我叫:" + Thread.currentThread().getName());
try {
System.out.println(Thread.currentThread().getName() + "休眠3秒");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 运行结束");
}
@Override
public void run() {
method();
}
public static void main(String[] args) {
Long startTime = System.currentTimeMillis();
// instatnce1,instatnce2 不同的2个实例,如果不加 static 就可以同时运行。
Thread t1 = new Thread(instatnce1);
Thread t2 = new Thread(instatnce2);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
Long endTime = System.currentTimeMillis();
System.out.println("finished 耗时"+(endTime-startTime));
}
}

对应的锁是同一把,一个一个的顺序执行。
4.同时访问同步方法与非同步方法
/**
* @author sxylml
* @Date : 2019/2/26 11:09
* @Description: 同时访问同步方法与非同步方法
*/
public class SynchronizedYesOrNo implements Runnable {
static Runnable instance1 = new SynchronizedYesOrNo();
@Override
public void run() {
if ("Thread-0".equals(Thread.currentThread().getName())) {
method1();
} else {
method2();
}
}
public synchronized void method1(){
System.out.println("我是synchronized 修饰的加锁的方法:我叫" + 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) {
Long startTime = System.currentTimeMillis();
// 两个线程访问的是两个对象的同步方法,同时开始,同时结束,可以理解并行执行的
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance1);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
while (t1.isAlive() || t2.isAlive()) {
}
Long endTime = System.currentTimeMillis();
System.out.println("整个程序运行结束! 用时" + (endTime - startTime));
}
}

非同步方法不受影响。
5.访问同一个对象的不同的普通同步方法
/**
* @author sxylml
* @Date : 2019/2/26 11:19
* @Description: 访问同一个对象的不同的普通同步方法
*/
public class SynchronizedDifferentMethod implements Runnable {
static Runnable instance = new SynchronizedDifferentMethod();
@Override
public void run() {
if ("Thread-0".equals(Thread.currentThread().getName())) {
method1();
} else {
method2();
}
}
public synchronized void method1() {
System.out.println("我是synchronized 修饰的加锁的方法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("我是synchronized 修饰的加锁的方法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) {
Long startTime = System.currentTimeMillis();
// 两个线程访问的是两个对象的同步方法,同时开始,同时结束,可以理解并行执行的
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
while (t1.isAlive() || t2.isAlive()) {
}
Long endTime = System.currentTimeMillis();
System.out.println("整个程序运行结束! 用时" + (endTime - startTime));
}
}

拿到的是this 锁,所以呢,还是会受影响,串行执行。
6.同时访问静态synchronized和 非静态synchronized
/**
* @author sxylml
* @Date : 2019/2/26 11:19
* @Description: 同时访问静态synchronized和 非静态synchronized
* 由于锁的对象不一样,所以同时执行
*/
public class SynchronizedStaticAndNormal implements Runnable {
static Runnable instance = new SynchronizedStaticAndNormal();
@Override
public void run() {
if ("Thread-0".equals(Thread.currentThread().getName())) {
method1();
} else {
method2();
}
}
public synchronized static void method1() {
System.out.println("我是synchronized 修饰静态static 的加锁的方法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("我是synchronized 修饰的加锁的方法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) {
Long startTime = System.currentTimeMillis();
// 两个线程访问的是两个对象的同步方法,同时开始,同时结束,可以理解并行执行的
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while (t1.isAlive() || t2.isAlive()) {
}
while (t1.isAlive() || t2.isAlive()) {
}
Long endTime = System.currentTimeMillis();
System.out.println("整个程序运行结束! 用时" + (endTime - startTime));
}
}

7.方法抛出异常后,会释放锁。
总结:
1.一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待(对应1,5题)
2.每一个实例都对应有自己的一把锁,不同实例之间互不影响,列外:
.锁对象是 *.class 以及synchronized 修饰的是static 方法的时候,所有对象公用一把类锁(对应,2,3,4,6)
3无论方法正常执行完毕或者方法抛出异常,都会释放锁。
4.目前进入被synchronized 的方法,在这方法里面调用没有synchronized 修饰的方法。还是线程安全的吗?
不是线程安全的,出了synchronized 就可以同时被多个线程调用。
网友评论