您的位置:首页 > 编程语言 > Java开发

java多线程-synchronized

2016-03-31 17:37 399 查看
synchronized是Java中使用的最基本的一个同步方法,使用 synchronized关键字来控制并发访问方法。只有一个执行线程将会访问一个对象中被synchronized关键字声明的方法。如果另一个线程试图访问同一个对象中任何被synchronized关键字声明的方法,它将被暂停,直到第一个线程结束方法的执行。

每个方法声明为synchronized关键字是一个临界区,Java只允许一个对象执行其中的一个临界区。

静态方法有不同的行为。只有一个执行线程访问被synchronized关键字声明的静态方法,但另一个线程可以访问该类的一个对象中的其他非静态的方法。 你必须非常小心这一点,因为两个线程可以访问两个不同的同步方法,如果其中一个是静态的而另一个不是。如果这两种方法改变相同的数据,你将会有数据不一致 的错误

同一个类中有多个synchronized关键字声明的静态方法。只要有一个线程访问了其中一个,其它线程则不可以访问任务一个synchronized关键字声明的静态方法,但可以访问该类其它同步方法和普通方法。

示例:

import java.util.Scanner;

public class SynchronizedTest {

public static synchronized void test1(){
System.out.println(Thread.currentThread().getName()+"进入阻塞!任意键结束!");
Scanner a = new Scanner(System.in);
a.next();

}

public static synchronized void test2(){
System.out.println(Thread.currentThread().getName()+"进入阻塞!任意键结束!");
Scanner a = new Scanner(System.in);
a.next();
}

public synchronized void test3(){
System.out.println(Thread.currentThread().getName()+"开始运行!");
System.out.println(Thread.currentThread().getName()+"请稍等...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束!");
}

public void test4(){
System.out.println(Thread.currentThread().getName()+"没有阻塞,运行结束!");
}

public static void main(String[] args) {
Thread a = new Thread(new Runnable(){
@Override
public void run() {
SynchronizedTest.test1();
}
});

Thread b = new Thread(new Runnable(){
@Override
public void run() {
SynchronizedTest.test2();
}
});

Thread c = new Thread(new Runnable(){
@Override
public void run() {
new SynchronizedTest().test3();
}
});

Thread d = new Thread(new Runnable(){
@Override
public void run() {
new SynchronizedTest().test3();;
}
});

Thread e = new Thread(new Runnable(){
@Override
public void run() {
new SynchronizedTest().test4();;
}
});

final SynchronizedTest syn = new SynchronizedTest();
Thread f = new Thread(new Runnable(){
@Override
public void run() {
syn.test3();;
}
});

Thread g = new Thread(new Runnable(){
@Override
public void run() {
syn.test3();;
}
});

a.setName("线程1");
b.setName("线程2");
c.setName("线程3(与线程4不同对象的同一任务)");
d.setName("线程4(与线程3不同对象的同一任务)");
e.setName("线程5");
f.setName("线程6(与线程7同对象的同一任务)");
g.setName("线程7(与线程6同对象的同一任务)");

a.start();
b.start();
c.start();
d.start();
e.start();
f.start();
g.start();

}
}


结果:

线程1进入阻塞!任意键结束!
线程4(与线程3不同对象的同一任务)开始运行!
线程4(与线程3不同对象的同一任务)请稍等...
线程6(与线程7同对象的同一任务)开始运行!
线程6(与线程7同对象的同一任务)请稍等...
线程3(与线程4不同对象的同一任务)开始运行!
线程3(与线程4不同对象的同一任务)请稍等...
线程5没有阻塞,运行结束!
线程4(与线程3不同对象的同一任务)运行结束!
线程6(与线程7同对象的同一任务)运行结束!
线程3(与线程4不同对象的同一任务)运行结束!
线程7(与线程6同对象的同一任务)开始运行!
线程7(与线程6同对象的同一任务)请稍等...
线程7(与线程6同对象的同一任务)运行结束!
d
线程2进入阻塞!任意键结束!
d


可以看到:

线程6与线程7 排队执行

线程3与线程6 没有排队

线程1与线程2 排队执行

线程1阻塞时,其它非静态方法都能顺利执行
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  同步 synchroniz 并发