public class TestSynchronized{
public static void main(String args[]){
TestThread t = new TestThread();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}class TestThread implements Runnable{
int num = 100;
String str = new String();
public void run(){
synchronized(str){
//锁str对象什么意思?
while(true){
if(num>0){
try{
Thread.sleep(10);
}catch(Exception e){
e.getMessage();
}
System.out.println(Thread.currentThread().getName()+"this is"+num--);
}else{
System.out.println("over");
break;
}
}
}
}
}rt,不明白,和synchronized(this)的效果一样的?
这样再试试。
synchronized是否达到你要的效果,你就检查看看是否多个线程需要锁定的内存区域都是同一个内存区域,相当于就是多个引用是否都指向同一个实例。
synchronized(str){}但结果又不一样了,为啥?
去掉synchronized(str){}但结果又不一样了,为啥?
public static void main(String args[]){
TestThread t = new TestThread();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}class TestThread implements Runnable{
int num = 100;
String str = new String();
public void run(){
synchronized(str){
//锁str对象什么意思?
int runTime = 0;
while(runTime < 100){
runTime++;
// if(num>0){
try{
Thread.sleep(10);
}catch(Exception e){
e.getMessage();
}
System.out.println(Thread.currentThread().getName()+"this is"+num--);
// }else{
// System.out.println("over");
// break;
// }
}
}
}
}这样改一下就是每个线程运行100次循环。在这个例子里锁住str相当于锁住this。锁住了就能线程同步了呀,每个线程循序访问num。
但是如果该为
public class TestSynchronized{
public static void main(String args[]){
TestThread t = new TestThread();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
}class TestThread implements Runnable{
int num = 100;
String str = new String();
public void run(){
str = new String(); //这样就达不到锁住this的效果了。
synchronized(str){
//锁str对象什么意思?
int runTime = 0;
while(runTime < 100){
runTime++;
// if(num>0){
try{
Thread.sleep(10);
}catch(Exception e){
e.getMessage();
}
System.out.println(Thread.currentThread().getName()+"this is"+num--);
// }else{
// System.out.println("over");
// break;
// }
}
}
}
}
就达不到锁住this的效果了,因为这个时候str指向的实例已经不是同一个了。
public class TestSynchronized{
public static void main(String args[]){
TestThread t = new TestThread();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
while(true)
{
try{
Thread.sleep(1000);
}catch(Exception e){
e.getMessage();
}
t.printNum();
}
}
}class TestThread implements Runnable{
int num = 100;
String str = new String();
public void run(){
synchronized(str){
// synchronized(this){
//锁str对象什么意思?
while(true){
if(num>0){
try{
Thread.sleep(100);
}catch(Exception e){
e.getMessage();
}
System.out.println(Thread.currentThread().getName()+"this is"+num--);
}else{
System.out.println("over");
break;
}
}
}
}
synchronized public void printNum()
{
System.out.println(Thread.currentThread().getName()+" this is "+num);
}
}
看看 synchronized(str){
// synchronized(this){
注释一个,换着看看效果是不是不一样了。如果把TestThread锁掉,那synchronized public void printNum()就不能访问了。如果只是锁掉str,那synchronized public void printNum()还是能访问的。
Public synchronized void method(){
//….
}
这也就是同步方法,那这时synchronized锁定的是哪个对象呢?他锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,他们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却能够任意调用这个被加了synchronized关键字的方法。
上边的示例代码等同于如下代码:
public void method()
{
synchronized (this) // (1)
{
//…..
}
}
(1)处的this指的是什么呢?他指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程,才能够调用P1的同步方法,而对P2而言,P1这个锁和他毫不相干,程式也可能在这种情形下摆脱同步机制的控制,造成数据混乱:(
2.同步块,示例代码如下:
public void method(SomeObject so) {
synchronized(so)
{
//…..
}
}
这时,锁就是so这个对象,谁拿到这个锁谁就能够运行他所控制的那段代码。当有一个明确的对象作为锁时,就能够这样写程式,但当没有明确的对象作为锁,只是想让一段代码同步时,能够创建一个特别的instance变量(他得是个对象)来充当锁:
class Foo implements Runnable
{
private byte[] lock = new byte[0]; // 特别的instance变量
Public void method()
{
synchronized(lock) { //… }
}
//…..
}
注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。 摘自http://leo-faith.javaeye.com/blog/177779
2:对于“锁”我的理解是:任意一个 java 对象都在其内部维持着一个“唯一的锁”,以实现多线程控制。可以粗糙的认为,每一个对象(无论是同一类型,还是不同类型的对象)都是独立的一把锁。
3:锁的作用:锁住一个域(这个域可以是方法,也可以是一个代码段),使得该域每次只能有一个“使用该锁的线程”访问。
4:锁的使用:需要配合 synchronized 关键字来使用。
第一种情况,通过 synchronized 和一把锁实现多线程对一个“非方法域”的串行访问。例如:private Object lock;
public void operating() {
synchronized(lock){
//....
}
} 第二中情况,实现多线程对一个方法的串行访问.例如:public synchronized void operating() {
//....
} 当使用 synchronized 控制多线程对一个方法的串行访问时,实际上使用的是当前对象(即调用该方法的对象)做为锁。
当你使用 synchronized 修饰了一个域时,肯定要有一个锁与其配套使用,如果你没显示的指定锁,那么就是使用当前对象作为锁(例如对方法使用 synchronized)。
5:对于初学者(例如《原来的我》)有一个弯要转过来:不同的对象就是不同的锁。在多线程访问 synchronized 域时,只有所有线程使用的是同一把锁,才能实现串行访问,即同步。
例如://这个写法相当弱,如果不是反面教材,我想没人会这么写。但我在初学时却总犯类似的错误。当然犯错时也不是写成这样,而是从外部传递了不同的锁。所以自己总结出这个写法,以警戒。
synchronized(new Object()){
}这段代码显然是不能实现同步的,各个线程使用的锁都不一样。
对于另一些初学者(例如 LZ)又要有一个弯要转过来:只要所有线程使用的是同一把锁,就能实现同步。 所以说在你的例子中:public class TestSynchronized{
public static void main(String args[]){
TestThread t = new TestThread();
new Thread(t).start();//线程1
new Thread(t).start();//线程2
new Thread(t).start();//线程3
}
}class TestThread implements Runnable{
int num = 100;
String str = new String();
public void run(){
synchronized(str){ //在该例中,这里等效于 synchronized(this){
while(true){
if(num>0){
try{
Thread.sleep(10);
}catch(Exception e){
e.getMessage();
}
System.out.println(Thread.currentThread().getName()+"this is"+num--);
}else{
System.out.println("over");
break;
}
}
}
}
}对于 线程1 ,线程2,线程3 来说,在访问 synchronized 所修饰的域时,他们使用的是同一把锁,即 t.str 。因为在 线程1 ,线程2,线程3 中 t.str 是“同一个对象”。
而如果该成 synchronized(this) 在该例中它与 synchronized(str) 是等效的。因为对于 synchronized(this) 来说 线程1 ,线程2,线程3 使用的也是同一把锁,即 t 。“只要所有线程使用的是同一把锁,就能实现同步。”对于 JVM 它不在乎你使用的锁是哪种类型。它关注的是使用的是否是同一把锁。