diff --git a/test/core/support/stack_lockfree_test.c b/test/core/support/stack_lockfree_test.c
index 4b6cf3f89b9..ebee04d5b89 100644
--- a/test/core/support/stack_lockfree_test.c
+++ b/test/core/support/stack_lockfree_test.c
@@ -33,20 +33,23 @@
 
 #include "src/core/support/stack_lockfree.h"
 
-#include <stddef.h>
 #include <stdlib.h>
-#include <string.h>
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include <grpc/support/useful.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
 #include "test/core/util/test_config.h"
 
-void test_serial() {
-  gpr_stack_lockfree *stack = gpr_stack_lockfree_create(128);
+/* max stack size supported */
+#define MAX_STACK_SIZE 65534
+
+#define MAX_THREADS 32
+
+static void test_serial_sized(int size) {
+  gpr_stack_lockfree *stack = gpr_stack_lockfree_create(size);
   int i;
-  
+
   /* First try popping empty */
   GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1);
 
@@ -54,22 +57,98 @@ void test_serial() {
   gpr_stack_lockfree_push(stack, 3);
   GPR_ASSERT(gpr_stack_lockfree_pop(stack) == 3);
   GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1);
-  
+
   /* Now add repeatedly more items and check them */
-  for (i=0; i<128; i++) {
+  for (i=1; i<size; i*=2) {
     int j;
     for (j=0; j<=i; j++) {
       gpr_stack_lockfree_push(stack, j);
     }
     for (j=0; j<=i; j++) {
-      GPR_ASSERT(gpr_stack_lockfree_pop(stack) == i-j);      
+      GPR_ASSERT(gpr_stack_lockfree_pop(stack) == i-j);
     }
     GPR_ASSERT(gpr_stack_lockfree_pop(stack) == -1);
   }
+
+  gpr_stack_lockfree_destroy(stack);
+}
+
+static void test_serial() {
+  int i;
+  for (i=128; i<MAX_STACK_SIZE; i*=2) {
+    test_serial_sized(i);
+  }
+  test_serial_sized(MAX_STACK_SIZE);
+}
+
+struct test_arg {
+  gpr_stack_lockfree *stack;
+  int stack_size;
+  int nthreads;
+  int rank;
+  int sum;
+};
+
+static void test_mt_body(void *v) {
+  struct test_arg *arg = (struct test_arg *)v;
+  int lo, hi;
+  int i;
+  int res;
+  lo = arg->rank*arg->stack_size/arg->nthreads;
+  hi = (arg->rank+1)*arg->stack_size/arg->nthreads;
+  for (i=lo; i<hi; i++) {
+    gpr_stack_lockfree_push(arg->stack, i);
+    if ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) {
+      arg->sum += res;
+    }
+  }
+  while ((res = gpr_stack_lockfree_pop(arg->stack)) != -1) {
+    arg->sum += res;
+  }
+}
+
+static void test_mt_sized(int size, int nth) {
+  gpr_stack_lockfree *stack;
+  struct test_arg args[MAX_THREADS];
+  gpr_thd_id thds[MAX_THREADS];
+  int sum;
+  int i;
+  gpr_thd_options options = gpr_thd_options_default();
+
+  stack = gpr_stack_lockfree_create(size);
+  for (i=0; i<nth; i++) {
+    args[i].stack = stack;
+    args[i].stack_size = size;
+    args[i].nthreads = nth;
+    args[i].rank = i;
+    args[i].sum = 0;
+  }
+  gpr_thd_options_set_joinable(&options);
+  for (i = 0; i < nth; i++) {
+    GPR_ASSERT(gpr_thd_new(&thds[i], test_mt_body, &args[i], &options));
+  }
+  sum = 0;
+  for (i = 0; i < nth; i++) {
+    gpr_thd_join(thds[i]);
+    sum = sum + args[i].sum;
+  }
+  GPR_ASSERT((unsigned)sum == ((unsigned)size*(size-1))/2);
+  gpr_stack_lockfree_destroy(stack);
+}
+
+static void test_mt() {
+  int size, nth;
+  for (nth=1; nth < MAX_THREADS; nth++) {
+    for (size=128; size < MAX_STACK_SIZE; size*=2) {
+      test_mt_sized(size,nth);
+    }
+    test_mt_sized(MAX_STACK_SIZE,nth);
+  }
 }
 
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_serial();
+  test_mt();
   return 0;
 }