package com.lee.thread;
public class TraditionalThreadSynchronized {
public static void main(String[] args) {
//静态方法中不能new内部类的实例对象
new TraditionalThreadSynchronized().init();
}
private void init(){
final Outputer outputer = new Outputer();
//线程1
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
outputer.output("zhangxiaoxiang");
}
}
}).start();
//线程2
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
outputer.output("lihuoming");
}
}
}).start();
}
class Outputer{
public void output(String name){
int len = name.length();
for(int i = 0; i < len; i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
线程1和线程2在外部类的init方法中,同时开启了,两个线程夺取内部类的资源,于是会出现线程1夺取一半时,线程2过来夺取。而本意是想,线程1执行一个,线程2执行一个。
输出结果如下:
zhangxiaoxlihuoming
iang
lihuozhanming
gxiaoxiang
lihuoming
zhangxiaoxiang
lihuoming
zhangxiaoxiang
lihzhangxiaoxiang
uoming
lihuozhming
因此,出现了所谓的线程安全隐患。
保证原子性,需要给并发的代码块加锁。
不过下面的方式是错误的
class Outputer{
public void output(String name){
synchronized (name) {
int len = name.length();
for(int i = 0; i < len; i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
synchronized里边的是一个栓子,应该是所有线程对象都用的是同一个栓子才可以达到互斥的效果。上面的写法,每个线程都有自己的传过来的不同的name,因此,起不到互斥效果。
输出效果如下:
ang
lihuoming
zhangxiaoxiang
lihuoming
zhangxiaoxiang
lizhangxiaoxiang
huoming
lihuomzhangxiaoxiang
ing
因此,实现互斥的锁,应该是每个线程都持有的一样的一把锁(这把锁必须是同一个对象的,如果每个线程都new了一个Outputer就不能实现互斥了,因为不是同一个对象),因此,可以在类中定义一个String s,那么每个在使用这个类时,使用的锁都是s锁,可以实现互斥的效果。
class Outputer{
String s = "xxx";
public void output(String name){
synchronized (s) {
int len = name.length();
for(int i = 0; i < len; i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
输出结果如下:
lihuoming
lihuoming
zhangxiaoxiang
lihuoming
zhangxiaoxiang
zhangxiaoxiang
lihuoming
zhangxiaoxiang
lihuoming
lihuoming
zhangxiaoxiang
zhangxiaoxiang
可以使用当前对象this作为锁,这样也可以实现互斥,因为他们都是来自同一个唯一的new出来的对象。
class Outputer{
public void output(String name){
synchronized (this) {
int len = name.length();
for(int i = 0; i < len; i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
当两个线程分别调用下面两个方法的时候,也可以实现互斥的效果,因为这两个方法都是使用this作为锁。
public void output(String name){
synchronized (this) {
int len = name.length();
for(int i = 0; i < len; i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public synchronized void output2(String name){ {
int len = name.length();
for(int i = 0; i < len; i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
输出结果如下:
zhangxiaoxiang
lihuoming
zhangxiaoxiang
lihuoming
zhangxiaoxiang
lihuoming
静态时,不与锁关系,但是最好还是加
static class Outputer {
public void output(String name) {
synchronized (Outputer.class) {
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public synchronized void output2(String name) {
{
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public static synchronized void output3(String name) {
{
int len = name.length();
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}