
扫码关注微信公众号
回复“面试手册”,获取本站PDF版
回复“简历”,获取高质量简历模板
回复“加群”,加入程序员交流群
回复“电子书”,获取程序员类电子书
当前位置:
Java > Java并发高频面试题 > 34.synchronized关键字的使用方法
本文链接:https://www.mianshi.online/multi-thread-synchronized-use.html
synchronized主要有三种使用方式:修饰普通同步方法、修饰静态同步方法、修饰同步方法块。
- 修饰普通同步方法(实例方法)
class syncTest implements Runnable {
private static int i = 0; //共享资源
private synchronized void add() {
i++;
}
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
add();
}
}
public static void main(String[] args) throws Exception {
syncTest syncTest = new syncTest();
Thread t1 = new Thread(syncTest);
Thread t2 = new Thread(syncTest);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
这是一个非常经典的例子,多个线程操作i++
会出现线程不安全问题,这段代码的结果很容易得到
20000
大家可以再看看这段代码,猜一猜它的运行结果
class syncTest implements Runnable {
private static int i = 0; //共享资源
private synchronized void add() {
i++;
}
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
add();
}
}
public static void main(String[] args) throws Exception {
// syncTest syncTest = new syncTest();
Thread t1 = new Thread(new syncTest());
Thread t2 = new Thread(new syncTest());
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
结果为
18634
第二个示例中的add()
方法虽然也使用synchronized关键字修饰了,但是因为两次new syncTest()
操作建立的是两个不同的对象,也就是说存在两个不同的对象锁,线程t1和t2使用的是不同的对象锁,所以不能保证线程安全。那这种情况应该如何解决呢?因为每次创建的实例对象都是不同的,而类对象却只有一个,如果synchronized关键字作用于类对象,即用synchronized修饰静态方法,问题则迎刃而解。
- 修饰静态方法
只需要在add()
方法前用static修饰即可,即当synchronized作用于静态方法,锁就是当前的class对象。
class syncTest implements Runnable {
private static int i = 0; //共享资源
private static synchronized void add() {
i++;
}
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
add();
}
}
public static void main(String[] args) throws Exception {
// syncTest syncTest = new syncTest();
Thread t1 = new Thread(new syncTest());
Thread t2 = new Thread(new syncTest());
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
结果为
20000
- 修饰同步代码代码块
如果某些情况下,整个方法体比较大,需要同步的代码只是一小部分,如果直接对整个方法体进行同步,会使得代码性能变差,这时只需要对一小部分代码进行同步即可。代码如下:
class syncTest implements Runnable {
static int i = 0; //共享资源
@Override
public void run() {
//其他操作.......
synchronized (this){ //this表示当前对象实例,这里还可以使用syncTest.class,表示class对象锁
for (int j = 0; j < 10000; j++) {
i++;
}
}
}
public static void main(String[] args) throws Exception {
syncTest syncTest = new syncTest();
Thread t1 = new Thread(syncTest);
Thread t2 = new Thread(syncTest);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
}
输出结果:
20000
本站链接:https://www.mianshi.online,如需勘误或投稿,请联系微信:lurenzhang888
点击面试手册,获取本站面试手册PDF完整版