1,当一个类中两个方法上同时加上synchronized字段,创建该对象的实例,启动两个线程调用该对象的两个方法,发现也是必须等一个线程执行完成之后另外一个线程才能执行。
创建类
package com.test.run;
public class TestSynchronized {
public synchronized void minus() {
int count = 5;
for (int i = 0; i < 5; i++) {
count--;
System.out.println(Thread.currentThread().getName() + " - " + count);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
public synchronized void minus2() {
int count = 5;
for (int i = 0; i < 5; i++) {
count--;
System.out.println(Thread.currentThread().getName() + " - " + count);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
}
类的调用
public class Run {
public static void main(String[] args) {
final TestSynchronized test = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
test.minus();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
test.minus2();
}
});
thread1.start();
thread2.start();
}
}
输出结果
Thread-0 - 4
Thread-0 - 3
Thread-0 - 2
Thread-0 - 1
Thread-0 - 0
Thread-1 - 4
Thread-1 - 3
Thread-1 - 2
Thread-1 - 1
Thread-1 - 0
2,当同一个类中有两个方法,一个方法加synchronized一个方法不加,创建两个线程调用该对象的两个方法,那么这两个对象可同时执行互不影响。
创建类
public class TestSynchronized {
public synchronized void minus() {
int count = 5;
for (int i = 0; i < 5; i++) {
count--;
System.out.println(Thread.currentThread().getName() + " - " + count);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
public void minus2() {
int count = 5;
for (int i = 0; i < 5; i++) {
count--;
System.out.println(Thread.currentThread().getName() + " - " + count);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
}
调用类
public class Run2 {
public static void main(String[] args) {
final TestSynchronized test = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
test.minus();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
test.minus2();
}
});
thread1.start();
thread2.start();
}
}
执行结果
Thread-1 - 4
Thread-0 - 4
Thread-1 - 3
Thread-0 - 3
Thread-1 - 2
Thread-0 - 2
Thread-1 - 1
Thread-0 - 1
Thread-1 - 0
Thread-0 - 0
也就是说进行了同步的方法(加锁方法)和没有进行同步的方法(普通方法)是互不影响的,一个线程进入了同步方法,得到了对象锁,其他线程还是可以访问那些没有同步的方法(普通方法)。当获取到与对象关联的内置锁时,并不能阻止其他线程访问该对象,当某个线程获得对象的锁之后,只能阻止其他线程获得同一个锁。
3,类锁需要 synchronized 来修饰静态 static 方法
public static synchronized void test(){
// TODO
}
或
public static void test(){
synchronized (TestSynchronized.class) {
// TODO
}
}
4,
创建类
public class TestSynchronized {
public static synchronized void minus() {
int count = 5;
for (int i = 0; i < 5; i++) {
count--;
System.out.println(Thread.currentThread().getName() + " - " + count);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
public synchronized void minus2() {
int count = 5;
for (int i = 0; i < 5; i++) {
count--;
System.out.println(Thread.currentThread().getName() + " - " + count);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
}
}
调用类
public class Run {
public static void main(String[] args) {
final TestSynchronized test = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
TestSynchronized.minus();
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
test.minus2();
}
});
thread1.start();
thread2.start();
}
}
输出结果
Thread-1 - 4
Thread-0 - 4
Thread-0 - 3
Thread-1 - 3
Thread-0 - 2
Thread-1 - 2
Thread-0 - 1
Thread-1 - 1
Thread-1 - 0
Thread-0 - 0
从上面可以看出两个线程是交替进行的,也就是说类锁和对象锁是不一样的锁,是互相独立的。
5,同步代码块
当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行,另一个线程必须等待当前线程执行完这个同步代码块以后才能执行该代码块。当一个线程访问object的一个synchronized同步代码块时,另一个线程仍然可以访问该object对象中的非synchronized(this)同步代码块。
如下:
public class Optimize {
public void doLongTimeTask(){
try {
System.out.println("当前线程开始:" + Thread.currentThread().getName() +
", 正在执行一个较长时间的业务操作,其内容不需要同步");
Thread.sleep(2000);
synchronized(this){
System.out.println("当前线程:" + Thread.currentThread().getName() +
", 执行同步代码块,对其同步变量进行操作");
Thread.sleep(1000);
}
System.out.println("当前线程结束:" + Thread.currentThread().getName() +
", 执行完毕");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
final Optimize otz = new Optimize();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
otz.doLongTimeTask();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
otz.doLongTimeTask();
}
},"t2");
t1.start();
t2.start();
}
}
执行结果