本文目录一览:
java中实现同步的方法有哪两种?
Java的同步可以用synchronized关键字来实现。\x0d\x0a \x0d\x0asychronized可以同步代码,需要绑定一个对象,如synchronized(obj){}\x0d\x0a也可以同步一个方法,是对方法进行线程同步。如public void synchronized methodA(){}
浅谈Java多线程的同步问题
多线程的同步依靠的是对象锁机制 synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问
下面以一个简单的实例来进行对比分析 实例要完成的工作非常简单 就是创建 个线程 每个线程都打印从 到 这 个数字 我们希望线程之间不会出现交叉乱序打印 而是顺序地打印
先来看第一段代码 这里我们在run()方法中加入了synchronized关键字 希望能对run方法进行互斥访问 但结果并不如我们希望那样 这是因为这里synchronized锁住的是this对象 即当前运行线程对象本身 代码中创建了 个线程 而每个线程都持有this对象的对象锁 这不能实现线程的同步
代码 package vista; class MyThread implements java lang Runnable { private int threadId;
public MyThread(int id) { this threadId = id; }
@Override public synchronized void run() { for (int i = ; i ; ++i) { System out println( Thread ID: + this threadId + : + i); } } }
public class ThreadDemo { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { for (int i = ; i ; ++i) { new Thread(new MyThread(i)) start(); Thread sleep( ); } } }
从上述代码段可以得知 要想实现线程的同步 则这些线程必须去竞争一个唯一的共享的对象锁
基于这种思想 我们将第一段代码修改如下所示 在创建启动线程之前 先创建一个线程之间竞争使用的Object对象 然后将这个Object对象的引用传递给每一个线程对象的lock成员变量 这样一来 每个线程的lock成员都指向同一个Object对象 我们在run方法中 对lock对象使用synchronzied块进行局部封锁 这样就可以让线程去竞争这个唯一的共享的对象锁 从而实现同步
代码 package vista;
class MyThread implements java lang Runnable { private int threadId; private Object lock;
public MyThread(int id Object obj) { this threadId = id; this lock = obj; }
@Override public void run() { synchronized (lock) { for (int i = ; i ; ++i) { System out println( Thread ID: + this threadId + : + i); } } } }
public class ThreadDemo { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { Object obj = new Object(); for (int i = ; i ; ++i) { new Thread(new MyThread(i obj)) start(); Thread sleep( ); } } }
从第二段代码可知 同步的关键是多个线程对象竞争同一个共享资源即可 上面的代码中是通过外部创建共享资源 然后传递到线程中来实现 我们也可以利用类成员变量被所有类的实例所共享这一特性 因此可以将lock用静态成员对象来实现 代码如下所示
代码 package vista;
class MyThread implements java lang Runnable { private int threadId; private static Object lock = new Object();
public MyThread(int id) { this threadId = id; }
@Override public void run() { synchronized (lock) { for (int i = ; i ; ++i) { System out println( Thread ID: + this threadId + : + i); } } } }
public class ThreadDemo { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { for (int i = ; i ; ++i) { new Thread(new MyThread(i)) start(); Thread sleep( ); } } }
再来看第一段代码 实例方法中加入sychronized关键字封锁的是this对象本身 而在静态方法中加入sychronized关键字封锁的就是类本身 静态方法是所有类实例对象所共享的 因此线程对象在访问此静态方法时是互斥访问的 从而可以实现线程的同步 代码如下所示
代码 package vista;
class MyThread implements java lang Runnable { private int threadId;
public MyThread(int id) { this threadId = id; }
@Override public void run() { taskHandler(this threadId); }
private static synchronized void taskHandler(int threadId) { for (int i = ; i ; ++i) { System out println( Thread ID: + threadId + : + i); } } }
lishixinzhi/Article/program/Java/gj/201311/27441
java同步是什么意思
一般有两种方法同步方法和同步代码块
假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。
1.把synchronized当作函数修饰符时,示例代码如下:
PublicsynchronizedvoidmethodAAA()
{
//….
}
这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。
上边的示例代码等同于如下代码:
publicvoidmethodAAA()
{
synchronized(this)//(1)
{
//…..
}
}
(1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于objectreference。――那个拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱:(
2.同步块,示例代码如下:
publicvoidmethod3(SomeObjectso)
{
synchronized(so)
{
//…..
}
}
这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:
classFooimplementsRunnable
{
privatebyte[]lock=newbyte[0];//特殊的instance变量
PublicvoidmethodA()
{
synchronized(lock){//…}
}
//…..
}
注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Objectlock=newObject()则需要7行操作码。
3.将synchronized作用于static函数,示例代码如下:
ClassFoo
{
publicsynchronizedstaticvoidmethodAAA()//同步的static函数
{
//….
}
publicvoidmethodBBB()
{
synchronized(Foo.class)//classliteral(类名称字面常量)
}
}
代码中的methodBBB()方法是把classliteral作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。
记得在《EffectiveJava》一书中看到过将Foo.class和P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。
可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized的instance函数B,那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。