class Test2
{
public Test2(int id)
{
MyThread2 test1 = new MyThread2(id);
test1.start();
}
class MyThread2 extends Thread
{
int id=0;
public MyThread2(int id)
{
this.id=id;
}
public void run()
{
synchronized(this)
{
for(int i=0;i++<50;)
System.out.println("id = "+id);
}
}
}
}
class Test3
{
public static void main(String[] args)
{
Test2 test = new Test2(1);
Test2 test2 = new Test2(2);
}
}我看到有个例子是这样用的,但我试了一下,好像不对.
请问synchronized(this)该怎么用?我不大懂.
上例中的this指的是Test2对象,还是MyThread2对象?
{
public Test2(int id)
{
MyThread2 test1 = new MyThread2(id);
test1.start();
}
class MyThread2 extends Thread
{
int id=0;
public MyThread2(int id)
{
this.id=id;
}
public void run()
{
synchronized(this)
{
for(int i=0;i++<50;)
System.out.println("id = "+id);
}
}
}
}
class Test3
{
public static void main(String[] args)
{
Test2 test = new Test2(1);
Test2 test2 = new Test2(2);
}
}我看到有个例子是这样用的,但我试了一下,好像不对.
请问synchronized(this)该怎么用?我不大懂.
上例中的this指的是Test2对象,还是MyThread2对象?
解决方案 »
- java中怎样实现这个侧边隐藏的控件呢?
- BorderLayout中遇到组件的大小问题
- hibernate连接集群oracle数据库
- 正则表达式怎样替换内容。谢了,救命啊!!!!!!!!!!!
- readInt()读出来的是高位在前,地位在后,可我要读的文件全是高位在后地位在前,怎么办?
- SWT达人入
- (earn money)i have java assingment that don't know how to do it, if people are intresting help me to do it,
- 帮忙分析一下这个基础题
- java -jar命令运行jar包出现的错误。
- List排序问题
- 在JAVA中的AWT中怎么将图片加到窗体和容积上面去
- JavaMail接收邮件,如何判断邮件为新邮件,邮件接收采用POP3
有时你只需要防止多个线程同时访问方法中的某一部分,而不是整个方法。这种需要隔离的代码就被称为关键段(critical section)。创建关键段需要用到synchronized关键词。这里,synchronized的作用是,指明执行下列代码需获得哪个对象的锁。synchronized(syncObject) {
// This code can be accessed
// by only one thread at a time
}关键段又被称为"同步块(synchronized block)";线程在执段代码之前,必须先获得syncObject的锁。如果其它线程已经获得这个锁了,那么在它解锁之前,线程不能运行关键段中的代码。同步分两种,代码的同步和方法的同步。下面这段例程比较了这两种方案。通过对比可以看出,相比同步整个方法,同步一段代码能显著增加其它线程获得这个对象的机会。此外,它还演示了如何用wrapper使用和保护非线程安全的类://: c13:CriticalSection.java
// Synchronizing blocks instead of entire methods. Also
// demonstrates protection of a non-thread-safe class
// with a thread-safe one.
import java.util.*;
class Pair { // Not thread-safe
private int x, y;
public Pair(int x, int y) {
this.x = x;
this.y = y;
}
public Pair() { this(0, 0); }
public int getX() { return x; }
public int getY() { return y; }
public void incrementX() { x++; }
public void incrementY() { y++; }
public String toString() {
return "x: " + x + ", y: " + y;
}
public class PairValuesNotEqualException
extends RuntimeException {
public PairValuesNotEqualException() {
super("Pair values not equal: " + Pair.this);
}
}
// Arbitrary invariant -- both variables must be equal:
public void checkState() {
if(x != y)
throw new PairValuesNotEqualException();
}
}
// Protect a Pair inside a thread-safe class:
abstract class PairManager {
protected Pair p = new Pair();
private List storage = new ArrayList();
public synchronized Pair getPair() {
// Make a copy to keep the original safe:
return new Pair(p.getX(), p.getY());
}
protected void store() { storage.add(getPair()); }
// A "template method":
public abstract void doTask();
}
// Synchronize the entire method:
class PairManager1 extends PairManager {
public synchronized void doTask() {
p.incrementX();
p.incrementY();
store();
}
}
// Use a critical section:
class PairManager2 extends PairManager {
public void doTask() {
synchronized(this) {
p.incrementX();
p.incrementY();
}
store();
}
}
class PairManipulator extends Thread {
private PairManager pm;
private int checkCounter = 0;
private class PairChecker extends Thread {
PairChecker() { start(); }
public void run() {
while(true) {
checkCounter++;
pm.getPair().checkState();
}
}
}
public PairManipulator(PairManager pm) {
this.pm = pm;
start();
new PairChecker();
}
public void run() {
while(true) {
pm.doTask();
}
}
public String toString() {
return "Pair: " + pm.getPair() +
" checkCounter = " + checkCounter;
}
}
public class CriticalSection {
public static void main(String[] args) {
// Test the two different approaches:
final PairManipulator
pm1 = new PairManipulator(new PairManager1()),
pm2 = new PairManipulator(new PairManager2());
new Timer(true).schedule(new TimerTask() {
public void run() {
System.out.println("pm1: " + pm1);
System.out.println("pm2: " + pm2);
System.exit(0);
}
}, 500); // run() after 500 milliseconds
}
} ///:~
你也看到了,Pair不是一个线程安全的类,它的invariant(我们随便定了一个)要求X和Y的值相同。此外,正如我们前面所看到的,递增不是线程安全的操作,而这些方法也都不是synchronized的,所以在多线程环境下,Pair肯定会出问题。PariManager包含一个Pair对象,与此同时它还控制了外部对这个对象的所有访问。注意,它的两个public方法,getPair( )和abstract doTash( )都是synchronized。只是后者的同步化处理放到了实现里面。PairManager的功能,有的是在abstract的基类里实现的,有的是在派生类里定义的。用设计模式的话来说,这就是是Template Method。[71]设计模式要求你把会变的代码封装起来;这里会变的就是模板方法doTask( )。PairManager1把整个doTask( )同步化了,而PairManager2用关键段部分地同步化了这个方法。注意,synchronized关键词不属于方法的特征签名,因此覆写的时候可以加上去。PairManager2值得关注。store( )是一个protected方法,也就是说只有子类才能访问,一般的客户根本是看不到的。所以我们就无需再把它放到synchronized方法里了。这里它被置于关键段之外。关键段必须要有对象来同步,最常见的就是这个方法自己所属的对象:synchronized(this)。PairManager2就用了这个方法。这样,当关键段获得对象锁的时候,其他线程就不能调用这个对象的synchronized方法了。而这样做的效果就是,大大缩小了同步的范围
然后synchronized(this)改成synchronized(obj)就OK了
class Producer extends Thread
{
CircularBuffer cbp=null;
Producer(CircularBuffer cb){cbp=cb;}
public void run(){
for(int i=0;i<=50000;i++)
try{
cbp.put(i);
}
catch (Exception err){
//System.
}
}
// public static void main(String[] args) {}
}
ProCum文件:package ProducerConsumer;
import java.io.*;
class ProCum{
public static void main(String[] args){
CircularBuffer cb=new CircularBuffer(20);
//因为要调用的两个方法put和get是排斥,所以调用时由同一个对象调用,所以
//都是cb,注意注意!!!!!!
Producer pro=new Producer(cb);
Consumer con=new Consumer(cb);
//
Thread a=null;
Thread b=null;
a=new Thread(pro);
b=new Thread(con);
b.start();
a.start();
}
}Consumer.java文件:package ProducerConsumer;
class Consumer extends Thread
{
CircularBuffer cbc=null;
Consumer(CircularBuffer cb)
{cbc=cb;}
public void run(){
for(int i=0;i<=50000;i++)
try{
cbc.get();
}
catch (Exception err){
}
}
}
CircularBuffer.java 文件:package ProducerConsumer;
import java.io.*;
class CircularBuffer
{
int bufsize;
int[] store;
int numOfEntries=0;
int front=0;
int back=0;
CircularBuffer(int n)
{
bufsize=n;
store=new int[bufsize];
}
synchronized void put(int obj)throws Exception{
if(numOfEntries==bufsize)
{
System.out.println("Producer waiting");
wait();
}
store[back]=obj;
back++;
if(back==bufsize) back=0;
else {numOfEntries++;
System.out.println("putting "+ obj);
notify();
}
}
synchronized int get() throws Exception{
int result=0;
if(numOfEntries==0)
{
System.out.println("Consumer waiting");
wait();
}
else{
result=store[front];
front++;
if(front==bufsize) front=0;
numOfEntries--;
System.out.println("getting "+result);//;
notify();
}
return result;
}
public static void main(String[] args)
{
}
}
class Test2
{
public Test2(int id)
{
MyThread2 test1 = new MyThread2(id);
test1.start();
}
class MyThread2 extends Thread
{
int id=0;
public MyThread2(int id)
{
this.id=id;
}
public void run()
{
Object obj=new Object();
synchronized(obj)
{
for(int i=0;i++<50;)
System.out.println("id = "+id);
}
}
}
}
class Test3
{
public static void main(String[] args)
{
Test2 test = new Test2(1);
Test2 test2 = new Test2(2);
}
}
你创建了2个MyThread2对象 并不是一个
2个MyThread2对象各拥有自己的字段和方法互不影响
{
static synchronized void pp(int id){
for(int i=0;i++<10;){
System.out.println(i+" "+"id = "+id);}
} public Test2(int id)
{
MyThread2 test1 = new MyThread2(id);
test1.start();
}
class MyThread2 extends Thread
{
int id=0;
public MyThread2(int id)
{
this.id=id;
}
public void run()
{ pp(id);
//synchronized(this)
//{
//}
}
}
}
public class Test3
{
public static void main(String[] args)
{
Test2 test = new Test2(1);
Test2 test2 = new Test2(2);
Test2 test3 = new Test2(3);
}
}
同意楼上意见
楼主可参考此例加以理解