网站救助计划
1.为阅读体验,本站无任何广告,也无任何盈利方法,站长一直在用爱发电,现濒临倒闭,希望有能力的同学能帮忙分担服务器成本
2.捐助10元及以上同学,可添加站长微信lurenzhang888,备注捐助,网站倒闭后可联系站长领取本站pdf内容
3.若网站能存活下来,后续将会持续更新内容
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完整版