synchronized修饰不同位置的作用
例1:修饰多个方法
public class SynchronizedTest {
public static void main(String[] args) {
Hello hello = new Hello();
new Thread(hello::printA, "线程A").start();
new Thread(hello::printB, "线程B").start();
}
static class Hello {
synchronized void printA() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void printB() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
执行结果:全是线程A在执行。
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
...
例2:修饰多个代码块
public class SynchronizedTest {
public static void main(String[] args) {
Hello hello = new Hello();
new Thread(hello::printA, "线程A").start();
new Thread(hello::printB, "线程B").start();
}
static class Hello {
void printA() {
synchronized (this) {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
synchronized void printB() {
synchronized (this) {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
执行结果:全是线程A在执行。
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
...
例3:修饰一个方法,另一个方法不修饰
public class SynchronizedTest {
public static void main(String[] args) {
Hello hello = new Hello();
new Thread(hello::printA, "线程A").start();
new Thread(hello::printB, "线程B").start();
}
static class Hello {
void printA() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void printB() {
synchronized (this) {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
执行结果:A和B两个线程交替执行
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
...
例4:修饰一个对象,对象中的方法都不需要加锁(没有synchronized修饰)
public class SynchronizedTest {
public static void main(String[] args) {
Hello hello = new Hello();
synchronized (hello) {
new Thread(hello::printA).start();
}
synchronized (hello) {
new Thread(hello::printB).start();
}
}
static class Hello {
void printA() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void printB() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
输出,线程交替执行
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程B 我在打印
线程A 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
例5:修饰一个对象,对象中的方法一个有synchronized修饰,一个没有
public class SynchronizedTest {
public static void main(String[] args) {
Hello hello = new Hello();
synchronized (hello) {
new Thread(hello::printA, "线程A").start();
}
synchronized (hello) {
new Thread(hello::printB, "线程B").start();
}
}
static class Hello {
synchronized void printA() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void printB() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
执行结果:
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
例6: 修饰一个对象,对象中的方法都用synchronized修饰
public class SynchronizedTest {
public static void main(String[] args) {
Hello hello = new Hello();
synchronized (hello) {
new Thread(hello::printA, "线程A").start();
}
synchronized (hello) {
new Thread(hello::printB, "线程B").start();
}
}
static class Hello {
synchronized void printA() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void printB() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
执行结果:
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
例7:修饰类
public class SynchronizedTest {
public static void main(String[] args) {
Hello hello = new Hello();
synchronized (Hello.class) {
new Thread(hello::printA, "线程A").start();
new Thread(hello::printA, "线程B").start();
}
}
static class Hello {
void printA() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void printB() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
输出:
线程A 我在打印
线程B 我在打印
线程B 我在打印
线程A 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
例8: 修饰类中的静态方法,同时执行synchronized修饰的静态和方法和没有修饰的静态方法
public class SynchronizedTest {
public static void main(String[] args) {
new Thread(Hello::printA, "线程A").start();
new Thread(Hello::printB, "线程B").start();
}
static class Hello {
synchronized static void printA() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static void printB() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
输出:
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
线程A 我在打印
线程B 我在打印
例9: 修饰类中的静态方法,同时执行synchronized修饰的静态和方法
public class SynchronizedTest {
public static void main(String[] args) {
new Thread(Hello::printA, "线程A").start();
new Thread(Hello::printB, "线程B").start();
}
static class Hello {
synchronized static void printA() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized static void printB() {
for (; ; ) {
System.out.println(Thread.currentThread().getName() + " 我在打印");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
输出:
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
线程A 我在打印
总结一下:
- synchronized可以修饰静态方法、非静态方法、代码块、一个对象、一个类。
- 不管修饰的是谁,锁的都是synchronized 关键字后面的大括号包起来的部分。这一部分是不能被多线程同时访问的。
- 哪怕修饰的是对象或者类,只要多个线程执行的时候,不同时执行到对象或类中synchronized 修饰的部分,就可以执行。也就是说,给对象或者类加了锁,同时synchronized修饰的代码块和没有修饰的代码块都是可以的。