疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java synchronized关键字详解


 

 
synchronized是Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
 
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
 
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,相当于给该对象上锁,其他线程将不能访问该对象的其他synchronized修饰的块或方法。但是其他线程仍然能够访问该对象的非synchronized修饰的块或方法。
 
java 
public class ThreadTest {
 
public static void main(String[] args) {
 
    Example example = new Example();
 
    Thread t1 = new TheThread(example);
 
    Thread t2 = new TheThread2(example);
 
    t1.start();
 
    t2.start();
 
}
}
 
class Example{
 
public synchronized void execute(){
 
    for(int i = 0; i < 5; i ++){
 
        try {
            Thread.sleep((long)(Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        System.out.println("hello: " + i);
    }
}
 
public synchronized static void execute2()
{
    for(int i = 0; i < 5; i++)
    {
        try
        {
            Thread.sleep((long)(Math.random() * 1000));
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
 
        System.out.println("world: " + i);
    }
}
}
 
class TheThread extends Thread{
 
private Example example;
 
public TheThread(Example example){
    this.example = example;
}
 
@Override
public void run() {
    this.example.execute();
}
}
 
class TheThread2 extends Thread{
 
private Example example;
 
public TheThread2(Example example)
{   
    this.example = example;
}
 
@Override
public void run()
{
    this.example.execute2();
}
}
 
在这里,我们定义了两个线程类TheThread和TheThread2,两个类中都有Example对象,在两个线程类的run()方法中分别调用了Example对象的execute()和execute2()方法,两个方法都被synchronized修饰,调用main()方法后产生的结果不言而喻,如下:
hello: 0
hello: 1
hello: 2
hello: 3
hello: 4
world: 0
world: 1
world: 2
world: 3
world: 4
线程会访问完execute()后,再访问execute2()。即:当一个线程访问object的一个synchronized(this)同步代码块时,相当于给该对象上锁,其他线程将不能访问该对象的其他synchronized修饰的块或方法。
 
如果我们把execute()稍微改一下,去掉synchronized关键字。
 
“`java 
public void execute(){
 
    for(int i = 0; i < 5; i ++){
 
        try {
            Thread.sleep((long)(Math.random() * 1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
        System.out.println("hello: " + i);
    }
}
将会产生另外一种结果:
 
hello: 0
world: 0
hello: 1
world: 1
hello: 2
hello: 3
world: 2
hello: 4
world: 3
world: 4
相当于两个线程并发访问Example对象,当一个线程访问object的一个synchronized(this)同步代码块时,相当于给该对象上锁,但其他线程仍然能够访问该对象的非synchronized修饰的块或方法。