您的位置:首页 > 其它

传统线程互斥技术初步-synchronized常用的几个锁对象

2016-07-27 13:17 543 查看
—————-本系列文章作为学习张孝祥老师系列视频的笔记。—————

1.非同步情况下线程的运行

首先看一个程序:

public class TraditionalSynchronizedLock
{
public static void main(String[] args)
{
OutDemo out = new OutDemo();
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.output("i love vayne");
}
}
}).start();

new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.output("my csdn blog");
}
}
}).start();
}
}

class OutDemo
{
public void output(String string)
{
int len = string.length();
for (int i = 0; i < len; i++)
{
System.out.print(string.charAt(i));
}
System.out.println();
}
}


该程序的结构是一个定义了一个打印方法的外部类和一个启动2个线程的主类。

然后2个线程进入没有同步的打印语句块,从而产生了下列运行结果:

imy c slove vaynden bl
og
imy csdn blog
love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne


出现这样结果的原因是某一线程打印时被另一线程打断然后出现了打印混乱的情况。

2.使用一个额外的对象作为

现在我们给打印块加锁,注意这个锁必须是同一把锁,即用的锁对象是同一个:

程序如下:

public class TraditionalSynchronizedLock
{
public static void main(String[] args)
{
OutDemo out = new OutDemo();
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.output("i love vayne");
}
}
}).start();

new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.output("my csdn blog");
}
}
}).start();
}
}

class OutDemo
{
String lock = "";

public void output(String string)
{
int len = string.length();
synchronized (lock)
{
for (int i = 0; i < len; i++)
{
System.out.print(string.charAt(i));
}
System.out.println();
}
}
}


结果正常打印:

i love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne
my csdn blog
i love vayne
my csdn blog


从上面程序可以看出,锁是字符串对象lock,并且lock只有一个。2个线程用的都是一个lock;

3.使用对象锁

下面使用调用打印方法的OutDemo对象作为锁:

public class TraditionalSynchronizedLock
{
public static void main(String[] args)
{
OutDemo out = new OutDemo();
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.output("i love vayne");
}
}
}).start();

new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.output("my csdn blog");
}
}
}).start();
}
}

class OutDemo
{

public synchronized void output(String string)
{
int len = string.length();
for (int i = 0; i < len; i++)
{
System.out.print(string.charAt(i));
}
System.out.println();
}
}


运行结果正常,这里不贴出来了。

需要说明的是,如果在方法前面加synchronized为方法加锁,那么线程持有的锁对象是调用该方法的那个对象,比如上述程序的锁就是out这个对象。

4.使用类的字节码作为锁

现在我们来考虑这样一种情况:OutDemo类有一个打印方法是静态方法,而且该方法前面加了synchronized进行同步,那么此时它用的是哪个对象当锁呢?

我们知道,静态方法执行时不需要创建一个实例对象,那么我们此时要将该类的一个属性与锁联系起来,显然这个对象就是该类加载时产生的class对象。

另外,只要2个线程执行逻辑语句的时候,它们需要的锁是同一个锁,那么就能产生同步效果。比如线程A需要锁x来执行方法m,线程B执行方法n的时候也需要锁m,此时虽然它们执行不同的方法,但是需要的锁是一样的。因此也能产生同步效果。

下面是一个Demo:

public class TraditionalSynchronizedLock
{
public static void main(String[] args)
{
OutDemo out = new OutDemo();
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
OutDemo.output("i love vayne");
}
}
}).start();

new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(10);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
out.output2("my csdn blog");
}
}
}).start();
}
}

class OutDemo
{

public static synchronized void output(String string)
{
int len = string.length();
for (int i = 0; i < len; i++)
{
System.out.print(string.charAt(i));
}
System.out.println();
}

public void output2(String string)
{
int len = string.length();
synchronized (OutDemo.class)
{
for (int i = 0; i < len; i++)
{
System.out.print(string.charAt(i));
}
System.out.println();

}

}

}


该程序的运行结果也是正常打印的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程 张孝祥