您的位置:首页 > 其它

多线程下synchronized修饰static方法与非static方法的区别

2013-08-21 18:06 465 查看
一直对多线程的概念比较模糊,今天就写了个关于变量原子操作的小程序,好让自己加深一下理解

代码如下:

package atomic;

public class JoinThread extends Thread {

public static int i = 0;

//public static AtomicInteger atomicInteger = new AtomicInteger(0);

public synchronized void inc(){
i ++;
}
@Override
public void run() {
for (int x = 0; x < 10; x++) {
inc();
try {
Thread.sleep(33);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
// JoinThread jt = new JoinThread();
Thread[] t = new Thread[100];
for (int i = 0; i < t.length; i++) {
t[i] = new JoinThread();
}
for (int i = 0; i < t.length; i++) {
t[i].start();
}
for (int i = 0; i < t.length; i++) {
t[i].join();
}
System.out.println(JoinThread.i);
}

}


执行完发现,i并没有如想像中的输出1000,即使i添加volatile进行修饰,也不会输出1000,值是随机变化的。

将inc()方法添加static修饰,结果无问题,准确无误的输出1000。

另外一种改法,将代码改成:

Thread[] t = new Thread[100];
for (int i = 0; i < t.length; i++) {
t[i] = new JoinThread();
}
修改成:

JoinThread jt = new JoinThread();
Thread[] t = new Thread[100];
for (int i = 0; i < t.length; i++) {
t[i] = new Thread(jt);
}
结果无问题,准确无误的输出1000

这里主要涉及到类对象(static方法),对象方法(非static方法)

我们知道,当synchronized修饰一个static方法时,多线程下,获取的是类锁(即Class本身,注意:不是实例);

当synchronized修饰一个非static方法时,多线程下,获取的是对象锁(即类的实例对象)

所以,当synchronized修饰一个static方法时,创建线程不管是new JoinThread()还是new Thread(new JoinThread()),在run方法中执行inc()方法都是同步的;

相反,当synchronized修饰一个非static方法时,如果用new JoinThread()还是new Thread(new JoinThread())方式创建线程,就无法保证同步操作,因为这时

inc()是属于对象方法,每个线程都执有一个独立的对象实例new JoinThread(),所以多线程下执行inc()方法并不会产生互斥,也不会有同步操作。

另外如果考虑到变更的原子操作,可使用atomic包下面的包装对象,这些对象都是对volatile修饰变量的一种延伸,可保证变量的原子操作而不用去同步方法或

代码块是否同步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: