面试时的两个技术问题 讨论一下。。

  1. 全局变量num=0
      两个线程同时执行以下代码
      {
         for(int i=0;i<50;i++){
            num+=1;
         }
       }
       
      最终num值的范围是什么?


    2. 设计一个并发量100左右的系统 从服务器 应用 手段各个角度考虑



第一题应该是
50到100

并发100的话,考虑数据库连接池,缓存,并发安全上 使用锁,队列

tomcat 本身 默认支持的并发为200.配和连接池,完全给解决 第一个 50

就算阻塞了它还是要循环的啊
线程2这个时间很慢,按照你说的模拟了下
[code="java"]
static int num =0;

public static void c(){
    Thread t1 = new Thread(){
        @Override
        public void run() {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for(int i=0;i<50;i++)
            num+=1;
        }
    };

   Thread t2=   new Thread(){
        @Override
        public void run() {
            try {
                sleep(1000);
            for(int i=0;i<50;i++){
                    int temp = num;
                    if(i==0){
                        sleep(1000);
                        temp+=1;
                        num=temp;
                    }
            }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    t1.start();
    t2.start();
}
public static void main(String[] args) {
    c();
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(num);
}

[/code]

上面那个有点问题,保证线程2先拿到;
这里最后的结果就是1,,但是对于计算机来说
num+=1; 这里执行的时间是一样多的,所以并不会出现线程1执行完了,线程2才执行了1步这种情况
[code="java"]
static int num =0;

public static void c(){
    Thread t1 = new Thread(){
        @Override
        public void run() {
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            for(int i=0;i<50;i++)
            num+=1;
        }
    };

   Thread t2=   new Thread(){
        @Override
        public void run() {
            try {
                                   //线程2先拿到num,然后阻塞住
                sleep(999);
            for(int i=0;i<50;i++){
                    int temp = num;
                    if(i==0){
                        sleep(1000);
                        temp+=1;
                        num=temp;
                    }
            }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    t1.start();
    t2.start();
}
public static void main(String[] args) {
    c();
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(num);
}

[/code]

public static void main(String[] args){

    Thread thread1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for(int i=0;i<50;i++){
                num++;
                System.out.println(num);
            }
        }
    });

    Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for(int i=0;i<50;i++){
                num++;
                System.out.println(num);
            }
        }
    });

    thread1.start();
    thread2.start();
}

看了回答,同志们真心不看题啊,第一题问num最后的值是多少,不是让写程序。
个人感觉是50~100,测实测
第二题:并发量100该如何控控制,求教高手!这个真心不懂

要看主子线程的阻塞程度了。
如zhangzehao 所写,两个子线处理速度足够快,那结构就是100
如果子线程阻塞程度高,主线程没有阻塞那 也就是0或是1
总所有情况取之范围应该会在0-100之间

用scala写的,都是用的java的类库,你改成java代码就可以了,结果50-100.
[code="scala"]
object SzStudy extends App {
import java.util.LinkedList
import java.util.concurrent._
var num = 0
val pool = Executors.newFixedThreadPool(2)
val calls = new LinkedListCallable[Unit];
val call = new Callable[Unit] {
def call() {
for (i <- 0 to 49) {
num += 1
}
}
}
calls.addLast(call)
calls.addLast(call)
val fa = pool.invokeAll(calls)
val iter=fa.iterator
//阻塞主线程,等两个子线程运行完
while(iter.hasNext){
iter.next.get()
}
println(num)
}
[/code]

[quote]+ 和 =是两个操作吧 , 不会有这种情况: 线程1的+操作正在进行, 线程2的循环结束, 线程1才开始执行=操作吗。

还有int变量如果不加volatile关键字, 变量貌似是存放在各自的寄存器缓存里的, 而不一定什么时候才赋值给全局变量。。 有没有可能发生 线程2num赋值为50 而线程1重新把num变为1呢。。

或者线程2执行到49时, 线程1赋值给全局变量1 , 此时线程2拿到的num又变为1了?[/quote]其实差不多就是这样子的。。。。所以答案应该是50~100

  1. num+=1这个操作不具有原子性,并且mun至少被计算一次后泻入内存,因此从理论上讲,值的范围是1-100

  2. 这个要说的比较多,总的来说就是降低级别,少用锁,提高程序并发能力,话说回来100并发应该还可以,没那么多需要考虑的

[size=large][color=red]第一题应该是100.
无论线程什么时候阻塞,两个线程都会正常执行完,相当于执行两次+50

第二题
考虑连接池,重叠IO,端口重用等[/color][/size]

第一题:50-100
第二题:上网搜 一大把