java

位置:IT落伍者 >> java >> 浏览文章

浅谈Java多线程的同步问题


发布日期:2024年07月07日
 
浅谈Java多线程的同步问题

多线程的同步依靠的是对象锁机制synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问

下面以一个简单的实例来进行对比分析实例要完成的工作非常简单就是创建个线程每个线程都打印从个数字我们希望线程之间不会出现交叉乱序打印而是顺序地打印

先来看第一段代码这里我们在run()方法中加入了synchronized关键字希望能对run方法进行互斥访问但结果并不如我们希望那样这是因为这里synchronized锁住的是this对象即当前运行线程对象本身代码中创建了个线程而每个线程都持有this对象的对象锁这不能实现线程的同步

代码

package comvista;

class MyThread implements javalangRunnable {

private int threadId;

public MyThread(int id) {

thisthreadId = id;

}

@Override

public synchronized void run() {

for (int i = ; i < ; ++i) {

Systemoutprintln(Thread ID: + thisthreadId + : + 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();

Threadsleep();

}

}

}

从上述代码段可以得知要想实现线程的同步则这些线程必须去竞争一个唯一的共享的对象锁

基于这种思想我们将第一段代码修改如下所示在创建启动线程之前先创建一个线程之间竞争使用的Object对象然后将这个Object对象的引用传递给每一个线程对象的lock成员变量这样一来每个线程的lock成员都指向同一个Object对象我们在run方法中对lock对象使用synchronzied块进行局部封锁这样就可以让线程去竞争这个唯一的共享的对象锁从而实现同步

代码

package comvista;

class MyThread implements javalangRunnable {

private int threadId;

private Object lock;

public MyThread(int id Object obj) {

thisthreadId = id;

thislock = obj;

}

@Override

public void run() {

synchronized (lock) {

for (int i = ; i < ; ++i) {

Systemoutprintln(Thread ID: + thisthreadId + : + 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();

Threadsleep();

}

}

}

从第二段代码可知同步的关键是多个线程对象竞争同一个共享资源即可上面的代码中是通过外部创建共享资源然后传递到线程中来实现我们也可以利用类成员变量被所有类的实例所共享这一特性因此可以将lock用静态成员对象来实现代码如下所示

代码

package comvista;

class MyThread implements javalangRunnable {

private int threadId;

private static Object lock = new Object();

public MyThread(int id) {

thisthreadId = id;

}

@Override

public void run() {

synchronized (lock) {

for (int i = ; i < ; ++i) {

Systemoutprintln(Thread ID: + thisthreadId + : + 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();

Threadsleep();

}

}

}

再来看第一段代码实例方法中加入sychronized关键字封锁的是this对象本身而在静态方法中加入sychronized关键字封锁的就是类本身静态方法是所有类实例对象所共享的因此线程对象在访问此静态方法时是互斥访问的从而可以实现线程的同步代码如下所示

代码

package comvista;

class MyThread implements javalangRunnable {

private int threadId;

public MyThread(int id) {

thisthreadId = id;

}

@Override

public void run() {

taskHandler(thisthreadId);

}

private static synchronized void taskHandler(int threadId) {

for (int i = ; i < ; ++i) {

Systemoutprintln(Thread ID: + 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();

Threadsleep();

}

}

}

               

上一篇:Java深入分析之:使用Factory Method模式

下一篇:Java多线程调试如何完成信息输出处理