前面已经写过生产者与消费者的例子了,用到Synchronized关键字,这是java并发的一个关键点,锁机制,我不打算长篇大论,用几个概况的说明,然后每个说明加一段代码的方式来讲解:
一 当两个线程同时访问同一个Object的Synchronized方法或代码块的时候,一个时间只能一个线程执行这段代码,另外一个线程要等待前一个线程执行完这段代码才可以执行:
public class SynchronizedTest {
public static void main(String[] args) {
SynchronizedObject so = new SynchronizedObject();
MyThread t1 = new MyThread(so);
MyThread t2 = new MyThread(so);
Thread ta = new Thread(t1, "ThreadA");
Thread tb = new Thread(t2, "ThreadB");
ta.start();
tb.start();
}
}
class SynchronizedObject {
public void synchronizedFuc() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
}
class MyThread implements Runnable {
SynchronizedObject so = null;
public MyThread(SynchronizedObject so) {
this.so = so;
}
@Override
public void run() {
// TODO Auto-generated method stub
if (so != null) {
so.synchronizedFuc();
}
}
}
执行结果:
ThreadA0
ThreadA1
ThreadA2
ThreadA3
ThreadA4
ThreadA5
ThreadA6
ThreadA7
ThreadA8
ThreadA9
ThreadB0
ThreadB1
ThreadB2
ThreadB3
ThreadB4
ThreadB5
ThreadB6
ThreadB7
ThreadB8
ThreadB9
可以看到是第二个线程等第一个线程执行完相关的同步代码块才执行
二 当一个线程访问对象的Synchronized方法或者代码块的时候,另外一个线程扔可以访问该对象的非Synchronized方法,如下:
public class SynchronizedTest {
public static void main(String[] args) {
SynchronizedObject so = new SynchronizedObject();
MyThread t1 = new MyThread(so);
// MyThread t2 = new MyThread(so);
Thread ta = new Thread(t1, "ThreadA");
Thread tb = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
so.notSynchronizedFuc();
}
}, "ThreadB");
ta.start();
tb.start();
}
}
class SynchronizedObject {
public void synchronizedFuc() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
public void notSynchronizedFuc() {
for (int i = 0; i < 10; i++) {
System.out.println("非同步代码块" + Thread.currentThread().getName() + i);
}
}
}
class MyThread implements Runnable {
SynchronizedObject so = null;
public MyThread(SynchronizedObject so) {
this.so = so;
}
@Override
public void run() {
// TODO Auto-generated method stub
if (so != null) {
so.synchronizedFuc();
}
}
}
执行结果:
ThreadA0
非同步代码块ThreadB0
ThreadA1
非同步代码块ThreadB1
ThreadA2
非同步代码块ThreadB2
ThreadA3
非同步代码块ThreadB3
ThreadA4
非同步代码块ThreadB4
ThreadA5
非同步代码块ThreadB5
ThreadA6
非同步代码块ThreadB6
ThreadA7
非同步代码块ThreadB7
ThreadA8
非同步代码块ThreadB8
ThreadA9
非同步代码块ThreadB9
可以看到相互不影响
三 当一个线程访问对象的Synchronized方法或者代码块时,其他线程想要访问该对象的其他Synchronized方法或者代码块,仍将受阻,如下:
public class SynchronizedTest {
public static void main(String[] args) {
SynchronizedObject so = new SynchronizedObject();
MyThread t1 = new MyThread(so);
// MyThread t2 = new MyThread(so);
Thread ta = new Thread(t1, "ThreadA");
Thread tb = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
so.notSynchronizedFuc();
}
}, "ThreadB");
ta.start();
tb.start();
}
}
class SynchronizedObject {
public void synchronizedFuc() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
public synchronized void notSynchronizedFuc() {
for (int i = 0; i < 10; i++) {
System.out.println("非同步代码块" + Thread.currentThread().getName() + i);
}
}
}
class MyThread implements Runnable {
SynchronizedObject so = null;
public MyThread(SynchronizedObject so) {
this.so = so;
}
@Override
public void run() {
// TODO Auto-generated method stub
if (so != null) {
so.synchronizedFuc();
}
}
}
执行结果:
ThreadA0
ThreadA1
ThreadA2
ThreadA3
ThreadA4
ThreadA5
ThreadA6
ThreadA7
ThreadA8
ThreadA9
非同步代码块ThreadB0
非同步代码块ThreadB1
非同步代码块ThreadB2
非同步代码块ThreadB3
非同步代码块ThreadB4
非同步代码块ThreadB5
非同步代码块ThreadB6
非同步代码块ThreadB7
非同步代码块ThreadB8
非同步代码块ThreadB9
四 Synchronized控制代码块的时候,参数也可以是对象,一样可以锁定,如下:
public class SynchronizedTest {
public static void main(String[] args) {
MyObject my = new MyObject();
SynchronizedObject so = new SynchronizedObject(my);
MyThread t1 = new MyThread(so);
MyThread t2 = new MyThread(so);
Thread ta = new Thread(t1, "ThreadA");
Thread tb = new Thread(t2,"ThreadB");
ta.start();
tb.start();
}
}
class SynchronizedObject {
MyObject mo;
public SynchronizedObject(MyObject mo) {
this.mo = mo;
}
public void synchronizedFuc() {
synchronized (mo) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
}
class MyThread implements Runnable {
SynchronizedObject so = null;
public MyThread(SynchronizedObject so) {
this.so = so;
}
@Override
public void run() {
// TODO Auto-generated method stub
if (so != null) {
so.synchronizedFuc();
}
}
}
class MyObject {
public MyObject() {
}
}
执行结果:
ThreadA0
ThreadA1
ThreadA2
ThreadA3
ThreadA4
ThreadA5
ThreadA6
ThreadA7
ThreadA8
ThreadA9
ThreadB0
ThreadB1
ThreadB2
ThreadB3
ThreadB4
ThreadB5
ThreadB6
ThreadB7
ThreadB8
ThreadB9
可以看到,一样锁定了
五 以上情况必须是针对线程访问同一个对象,如果是不同对象呢,如下:
public class SynchronizedTest {
public static void main(String[] args) {
SynchronizedObject so = new SynchronizedObject();
SynchronizedObject so1 = new SynchronizedObject();
MyThread t1 = new MyThread(so);
MyThread t2 = new MyThread(so1);
Thread ta = new Thread(t1, "ThreadA");
Thread tb = new Thread(t2,"ThreadB");
ta.start();
tb.start();
}
}
class SynchronizedObject {
public void synchronizedFuc() {
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
}
class MyThread implements Runnable {
SynchronizedObject so = null;
public MyThread(SynchronizedObject so) {
this.so = so;
}
@Override
public void run() {
// TODO Auto-generated method stub
if (so != null) {
so.synchronizedFuc();
}
}
}
执行结果如下:
ThreadA0
ThreadB0
ThreadA1
ThreadB1
ThreadA2
ThreadB2
ThreadA3
ThreadB3
ThreadA4
ThreadB4
ThreadA5
ThreadB5
ThreadA6
ThreadB6
ThreadA7
ThreadB7
ThreadA8
ThreadB8
ThreadA9
ThreadB9
发现没有同步。
六 如果把synchronizedFuc方法改成static的,就不是锁住对象了,而是锁住类,即使是两个对象,也可以达到同步的效果,如下:
public class SynchronizedTest {
public static void main(String[] args) {
SynchronizedObject so = new SynchronizedObject();
SynchronizedObject so1 = new SynchronizedObject();
MyThread t1 = new MyThread(so);
MyThread t2 = new MyThread(so1);
Thread ta = new Thread(t1, "ThreadA");
Thread tb = new Thread(t2,"ThreadB");
ta.start();
tb.start();
}
}
class SynchronizedObject {
public synchronized static void synchronizedFuc() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
class MyThread implements Runnable {
SynchronizedObject so = null;
public MyThread(SynchronizedObject so) {
this.so = so;
}
@Override
public void run() {
// TODO Auto-generated method stub
if (so != null) {
so.synchronizedFuc();
}
}
}
执行结果如下:
ThreadA0
ThreadA1
ThreadA2
ThreadA3
ThreadA4
ThreadA5
ThreadA6
ThreadA7
ThreadA8
ThreadA9
ThreadB0
ThreadB1
ThreadB2
ThreadB3
ThreadB4
ThreadB5
ThreadB6
ThreadB7
ThreadB8
ThreadB9
七 如果想锁住类,可以直接Synchronized(X.class),如下:
public class SynchronizedTest {
public static void main(String[] args) {
SynchronizedObject so = new SynchronizedObject();
SynchronizedObject so1 = new SynchronizedObject();
MyThread t1 = new MyThread(so);
MyThread t2 = new MyThread(so1);
Thread ta = new Thread(t1, "ThreadA");
Thread tb = new Thread(t2, "ThreadB");
ta.start();
tb.start();
}
}
class SynchronizedObject {
public void synchronizedFuc() {
synchronized (SynchronizedObject.class) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + i);
}
}
}
}
class MyThread implements Runnable {
SynchronizedObject so = null;
public MyThread(SynchronizedObject so) {
this.so = so;
}
@Override
public void run() {
// TODO Auto-generated method stub
if (so != null) {
so.synchronizedFuc();
}
}
}
执行结果如下:
ThreadA0
ThreadA1
ThreadA2
ThreadA3
ThreadA4
ThreadA5
ThreadA6
ThreadA7
ThreadA8
ThreadA9
ThreadB0
ThreadB1
ThreadB2
ThreadB3
ThreadB4
ThreadB5
ThreadB6
ThreadB7
ThreadB8
ThreadB9
达到同步效果了
总结:
1 当两个线程同时访问同一个Object的Synchronized方法或代码块的时候,一个时间只能一个线程执行这段代码,另外一个线程要等待前一个线程执行完这段代码才可以执行。
2 当一个线程访问对象的Synchronized方法或者代码块的时候,另外一个线程扔可以访问该对象的非Synchronized方法。
3 当一个线程访问对象的Synchronized方法或者代码块时,其他线程想要访问该对象的其他Synchronized方法或者代码块,仍将受阻。
4 Synchronized控制代码块的时候,参数也可以是对象,一样可以锁定。
5 当线程访问不同对象时,用Synchronized修饰方法或者Synchronized(this),不能锁定。
6 如果把synchronizedFuc方法改成static的,就不是锁住对象了,而是锁住类,即使是两个对象,也可以达到同步的效果。
7 如果想锁住类,可以直接Synchronized(X.class)。
如有问题,欢迎指正,谢谢